Batch cant read txt from powershell

Hi. Sorry for my English - Im languagecripple.

I found nice script to take monitor serial. I need put serial and monitor model to txt file and after that read it by batch. But it doesnt work and i dont know why. I suppose that problem is in convert from ASCII code to char. Maybe first i show my batch code:

@echo off
    SETLOCAL EnableDelayedExpansion
    FOR /F "usebackq" %%v IN (`powershell -noprofile -executionpolicy bypass -File "mon.ps1"`) DO set "monitor=%%v"
    echo here is first tray with monitor variable: %monitor%
    echo.
    FOR /F "tokens=*" %%v IN (serial.txt) DO set "monitor=%%v"
    echo here is second tray with monitor variable: %monitor%
    echo.
    pause>nul

Now i show mon.ps1. First tray with simpler version:

$Monitory = gwmi -Namespace root\wmi -Class wmiMonitorID
   foreach ($Monitor in $Monitory)
   {
        $serial = $null
        $Monitor.SerialNumberID | foreach {$serial += [char]$_}

             if ($serial -ne 0)
            {
                   Remove-Item serial.txt
                   [System.IO.File]::AppendAllText("serial.txt", $serial, [System.Text.Encoding]::Unicode)
            }
   }

This code creates serial.txt with serial from my monitor, but batch doesnt show it. A little change and... batch show serial correct:

$Monitory = gwmi -Namespace root\wmi -Class wmiMonitorID
   foreach ($Monitor in $Monitory)
   {
        $serial = $null
        $Monitor.SerialNumberID | foreach {$serial += [char]$_}
        $serial
             if ($serial -ne 0)
            {
                   Remove-Item serial.txt
                   [System.IO.File]::AppendAllText("serial.txt", $serial, [System.Text.Encoding]::Unicode)
            }
   }

I dont know why when i put $serial, the output txt is different and batch see this serial. But i need serial and name:

$Monitory = gwmi -Namespace root\wmi -Class wmiMonitorID
$MonitorDetal = @()
foreach ($Monitor in $Monitory)
{
    $MonitorTemp = New-Object PSObject
    $serial = $null
    $name = $null
    $Monitor.SerialNumberID | foreach {$serial += [char]$_}
    $Monitor.UserFriendlyName | foreach {$name += [char]$_}

        if ($serial -ne 0)
        {
            $MonitorTemp = $serial 
            $MonitorTemp += $name
            $MonitorDetal += $MonitorTemp
        }
            else
        {
            $MonitorTemp = "empty " 
             $MonitorTemp += "empty"
             $MonitorDetal += $MonitorTemp
         }
}

                   Remove-Item serial.txt
                   [System.IO.File]::AppendAllText("serial.txt", $MonitorDetal, [System.Text.Encoding]::Unicode)What should I do with this?

August 23rd, 2015 9:16am

What is the purpose of this?   Why not just do it all in PowerShell?

Free Windows Admin Tool Kit Click here and download it now
August 23rd, 2015 12:24pm

Here is how to get the serial number of a monitor into an environment variable.

$sn=[System.Text.Encoding]::ASCII.GetString((gwmi wmiMonitorID -ns root\wmi).SerialNumberID)
[environment]::SetEnvironmentVariable('MonitorSN',$sn,'user') 

If there is no monitor serial number the environment variable will be set to '0'

August 23rd, 2015 12:45pm

Because i dont know powershell. And this is only one part of much bigger script.

Free Windows Admin Tool Kit Click here and download it now
August 23rd, 2015 3:10pm

Here is how to get the serial number of a monitor into an environment variable.

$sn=[System.Text.Encoding]::ASCII.GetString((gwmi wmiMonitorID -ns root\wmi).SerialNumberID)
[environment]::SetEnvironmentVariable('MonitorSN',$sn,'user') 

If there is no monitor serial number the environment variable will be set to '0'

August 23rd, 2015 3:29pm

powershell -command "$sn=[System.Text.Encoding]::ASCII.GetString((gwmi wmiMonitorID -ns root\wmi).SerialNumberID);[environment]::SetEnvironmentVariable('MonitorSN',$sn,'user')" 

Run it. Open a new CMD window and look at the environment

echo %MonitorSN%

Free Windows Admin Tool Kit Click here and download it now
August 23rd, 2015 3:39pm

powershell -command "$sn=[System.Text.Encoding]::ASCII.GetString((gwmi wmiMonitorID -ns root\wmi).SerialNumberID);[environment]::SetEnvironmentVariable('MonitorSN',$sn,'user')" 

Run it. Open a new CMD window and look at the environment

echo %MonitorSN%

August 24th, 2015 12:43pm

As I posted above.  You have to open a new command window to see the change.

Use one batch to run this PS script then call your other batch and it will get the setting since it was started after.  You cannot run the second batch with a "call" statement. it must be run directly.

Free Windows Admin Tool Kit Click here and download it now
August 24th, 2015 12:55pm

As I posted above.  You have to open a new command window to see the change.

Use one batch to run this PS script then call your other batch and it will get the setting since it was started after.  You cannot run the second batch with a "call" statement. it must be run directly.

August 25th, 2015 11:02am

What you want is to not do this with a batch file.  What you are asking is very vague.

Free Windows Admin Tool Kit Click here and download it now
August 25th, 2015 11:08am

What you want is to not do this with a batch file.  What you are asking is very vague.

August 25th, 2015 1:08pm

But your original script can only collect one monitor.  The code I posted also collects only one monitor.

You can try an catenate all monitors into one variable.

# place the following in a file called GetSerial.ps1
$sn=@()
gwmi wmiMonitorID -ns root\wmi|
   ForEach-Object{
       $sn+=[System.Text.Encoding]::ASCII.GetString($_.SerialNumberID)
   }
$serialNumbers=$sn -join ';'
[environment]::SetEnvironmentVariable('MonitorSN',$serialNumbers,'user')
$serialnumber

Call you file like this:

powershell -file GetSerial.ps1

That will put all serial numbers into one environment variable separated by |.

Or you can do this:

FOR /F "usebackq tokens=1,2* delims=;" %%i in (`powershell -file GetSerial.ps1`) do @echo Monitor1=%%i Monitor=%%j Monitor3=%%k

Free Windows Admin Tool Kit Click here and download it now
August 25th, 2015 1:41pm

But your original script can only collect one monitor.  The code I posted also collects only one monitor.

You can try an catenate all monitors into one variable.

# place the following in a file called GetSerial.ps1
$sn=@()
gwmi wmiMonitorID -ns root\wmi|
   ForEach-Object{
       $sn+=[System.Text.Encoding]::ASCII.GetString($_.SerialNumberID)
   }
$serialNumbers=$sn -join ';'
[environment]::SetEnvironmentVariable('MonitorSN',$serialNumbers,'user')
$serialnumber

Call you file like this:

powershell -file GetSerial.ps1

That will put all serial numbers into one environment variable separated by |.

Or you can do this:

FOR /F "usebackq tokens=1,2* delims=;" %%i in (`powershell -file GetSerial.ps1`) do @echo Monitor1=%%i Monitor=%%j Monitor3=%%k

August 25th, 2015 1:43pm

Eureka! I've done it! :-D

The problem was in ASCII code. Space between serial and name wasn't created by spaces (32 in ASCII code) but by NUL (0 in ASCII). Than i checked all ASCII codes and replaced 0 by 32.

Foreach ($i in $varall)
{
        if ($i -eq 0)
	{
	        $i = 32
		$varend += [char]$i
	}
	Else
	{
		$varend += [char]$i
	}
}
I used here two new variables - $varall has all info I need but in ASCII codes. $varend - all but after change 0 to 32 (NUL to space) and convert it to char. Than i put it to txt and now batch havent any problem with read it :-D
Free Windows Admin Tool Kit Click here and download it now
August 26th, 2015 1:23pm

Which is why I used the correct converter.

$sn=[System.Text.Encoding]::ASCII.GetString((gwmi wmiMonitorID -ns root\wmi).SerialNumberID)


August 26th, 2015 1:48pm

if($sn=[System.Text.Encoding]::ASCII.GetString((gwmi wmiMonitorID -ns root\wmi).SerialNumberID)){
    $sn
}else{
    'NO SERIALNUMBER'
}

Free Windows Admin Tool Kit Click here and download it now
August 26th, 2015 1:49pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics