Trying to search for a string within command output - windows

I'm writing a script to run PSinfo (from the Sysinternals suite) against a list of machines, then I want to search the output for a specific string before doing other things. The basic code is as follows:
with open ("specific-pcs.txt") as machines:
line = []
for machineName in machines:
machineName = machineName.strip()
ps_Info = subprocess.Popen("location of PsInfo \\" + machineName + " -s").communicate()[0]
if ("Silverlight" in ps_Info):
subprocess.Popen("wmic product where caption='Microsoft Silverlight' call uninstall")
print "Uninstalling Silverlight"
else:
pass
The output of PsInfo looks something like this:
Microsoft Office Word MUI (English) 2010 14.0.7015.1000
Microsoft ReportViewer 2010 Redistributable 10.0.30319
Microsoft Silverlight 5.1.10411.0
Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.4148 9.0.30729.4148
Realtek High Definition Audio Driver 6.0.1.7004
But running the code as is, it complains that "'Nonetype' is not iterable".
All I need it to do is say if Silverlight (in this case) exists in the output or not.
What do I need to change?
Thanks, Chris.

communicate returns None for a stream if it is not redirected to a pipe, which means in your case:
subprocess.Popen("location of PsInfo \\" + machineName + " -s").communicate()
will return (None, None), and when using the in operator on None you get the argument of type 'NoneType' is not iterable error.
Also, you should use a list of arguments when calling Popen instead of a single string, so this should work:
ps_Info = subprocess.Popen([r"C:\Path\To\PsInfo", r"\\" + machineName, "-s"],
stdout=subprocess.PIPE).communicate()[0]

Related

How to parse WMIC printer list full

When I use the following command, it outputs a text file with a computer's printer information: wmic printer list full >> c:\computer_printers.txt
However, the list is very long, and I only want to see the fields for DriverName, Name, and Portname in the output. Is there a way to modify the command I am using to get this result?
I researched the adverbs associated with the verb List, but the way I am interpreting the document here (https://msdn.microsoft.com/en-us/library/aa394531(v=vs.85).aspx), it does not seem like what I am trying to do is possible. Is there anyone with more experience with WMIC that can confirm this?
I only want to see the fields for DriverName, Name, and Portname in the output
Use the following command:
wmic printer get DriverName, Name, Portname >> c:\computer_printers.txt
Example output:
> type c:\computer_printers.txt
DriverName Name PortName
Microsoft XPS Document Writer Microsoft XPS Document Writer XPSPort:
Microsoft Shared Fax Driver Fax SHRFAX:
EPSON Stylus Photo RX560 Series EPSON Stylus Photo RX560 Series USB001
CutePDF Writer CutePDF Writer CPW2:
Further Reading
An A-Z Index of the Windows CMD command line | SS64.com
Windows CMD Commands (categorized) - Windows CMD - SS64.com
WMIC - Windows Management - Windows CMD - SS64.com

New-WebBinding: Cannot retrieve the dynamic parameters for the cmdlet

We're using Windows 2012 Server R2.
We're trying to automate the creation of LetsEncrypt certificates. We're using LetsEncrypt-Win-Simple (https://github.com/Lone-Coder/letsencrypt-win-simple).
Once the cert is created (via LetsEncrypt.exe) we have a .bat script that gets called (using the --script and --scriptparameters flags). This runs powershell.exe and tries to create the necessary IIS binding. The line in the .bat file is:
powershell.exe -file c:\temp\SSLIISBinding.ps1 %1 %2 %3 %4
The %1-4 are args passed in by LetsEncrypt. In the powershell script, the command we're trying to run is:
$iis_host_name = $args[0]
$iis_site_name = $args[1]
$certificate_hash = $args[2]
$certificate_store = $args[3]
"IIS Host Name: " + $iis_host_name
"IIS Site Name: " + $iis_site_name
"Certificate Hash: " + $certificate_hash
"Certificate Store: " + $certificate_store
$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert hostnameport="${iis_host_name}:443" certhash=$certificate_hash certstorename=$certificate_store appid="$guid"
New-WebBinding -name $iis_site_name -Protocol https -HostHeader $iis_host_name -Port 443 -SslFlags 1
The args are passed into the .bat fine, as we output them and they are showing correctly.
If we run the .bat file on its own, it works perfectly. If it gets called by LetsEncrypt.exe it fails, reporting the following issue:
New-WebBinding : Cannot retrieve the dynamic parameters for the cmdlet.
Retrieving the COM class factory for component with CLSID
{688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error:
80040154 Class not registered (Exception from HRESULT: 0x80040154
(REGDB_E_CLASSNOTREG)).
At C:\temp\SSLIISBinding.ps1:13 char:1
+ New-WebBinding -name $iis_site_name -Protocol https -HostHeader
$iis_host_name ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+ CategoryInfo : InvalidArgument: (:) [New-WebBinding], Parameter
BindingException
+ FullyQualifiedErrorId : GetDynamicParametersException,Microsoft.IIs.Powe
rShell.Provider.NewWebBindingCommand
I've googled, some mentioning something about 32bit vs 64bit powershell, but I've tried using all the different powershell.exe available.
Anyone hit this issue, or know to resolve.
If we call .bat directly from command line it works fine, just as part of being called via LetsEncrypt.exe. A permission problem? Wrong powershell.exe?
That part of your question:
I've googled, some mentioning something about 32bit vs 64bit powershell
is already half of an answer. Some commands do not run properly if bitness of PowerShell process does not match bitness of operation system. So, you need to run powershell.exe, which located in this %windir%\System32\WindowsPowerShell\v1.0\ directory. But there is a little problem described in this documentation topic:
In most cases, whenever a 32-bit application attempts to access %windir%\System32, the access is redirected to %windir%\SysWOW64.
Thus, if 32-bit program on 64-bit OS invoke %windir%\System32\WindowsPowerShell\v1.0\powershell.exe, it will actually invoke 32-bit version of PowerShell from here %windir%\SysWOW64\WindowsPowerShell\v1.0\ instead of 64-bit one. To actually invoke 64-bit PowerShell from 32-bit application you need to use this trick:
32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access.
I've got the same error when running the following cmdlet:
PS> Remove-WebAppPool -Name 'Test'
Remove-WebAppPool : Cannot retrieve the dynamic parameters for the cmdlet. Retrieving the COM class factory for
component with CLSID {688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error: 80040154 Class not
registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
At line:1 char:1
+ Remove-WebAppPool -Name 'Test'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Remove-WebAppPool], ParameterBindingException
+ FullyQualifiedErrorId : GetDynamicParametersException,Microsoft.IIs.PowerShell.Provider.RemoveAppPoolCommand
The reason was because I ran it using Windows PowerShell (x86) on my Windows 10 x64 machine.
When I tried the same but using Windows PowerShell, which is 64 bit version, it worked just fine.
I think your $guid is the issue. The GUID needs to be the GUID of the program to bind the cert to. For your example port 443 is only bound to a random GUID, and not your program's GUID. IIS and other apps have a static GUID that you will want to use. If the GUID for a powershell script then Get-host is the powershell host executing code so that's the GUID you need. It changes for every powershell session and the netsh binding needs to as well.
$appid = "appid={"+(get-host).InstanceId.guid+"}"
$certhash = ls Cert:\LocalMachine\my | where {$.EnhancedKeyUsageList -Match 'Server' -and $.subject -match (hostname)}|sort-object $_.NotAfter|select -expand Thumbprint -last 1
$cmdline='netsh http add sslcert ipport=0.0.0.0:443 certhash=' + $certhash + ' "' + $appid + '"'
netsh http delete sslcert ipport=0.0.0.0:443
Invoke-Expression $cmdline
A google search for "Cannot retrieve the dynamic parameters for the cmdlet" brought me here but my issue was using powershell from the command line, and the answer was to escape the double quotes on the command...
I've got a problem with the same error. This happens when i'm trying to Add-WebBinding to my IIS site remotely, using Invoke-Command from different agent machines at time.
It's worked for me, maybe it helps someone too:
$Mutex = New-Object -TypeName System.Threading.Mutex($false, "Global\Mutex")
if ($Mutex.WaitOne(300000)) {
#For example
#$Command = {
#New-WebBinding -name $iis_site_name -Protocol https -HostHeader
#$iis_host_name -Port 443 -SslFlags 1
#}
#Invoke-Command -Command $Command
} else {
Write-Warning "Timed out acquiring mutex!"
}
$Mutex.Dispose()

VBS - Error opening connection using ADODB

I'm having problems trying to connect in my oracle database using an ADODB object in VBScript, the code is working on a Win7 machine but not on WinXP, I tried to search for the error code, downloaded the sdk with the help file to look for something but I didn't found nothing useful.
Here is the code sample:
ConnectionString = "DSN=(Oracle in OraClient11g_home1);UID=username ;PWD=password ;DBQ=myDatabase"
Set objCon = CreateObject("ADODB.Connection")
objCon.Open ConnectionString 'the error occurs in this line
I don't know if the connection string must be different for winXP machines... I really don't know how to solve this, can someone help me?
The error trace information:
"Error #-2147024770:
Error reported by: ADODB.Connection
Help File:
Topic ID: 1240640"
-2147024770 = FFFFFFFF8007007E
To Decode 0x8007nnnn Errors
HResults with facility code 7 means the HResult contains a Windows' error code. You have to look up the Windows' error code not the HResult.
To decode 0x8007007e. The 0x means it's a hexadecimal number, the 8 means error, the first 7 means it a windows error, and the rest of the number, 7e, is the actual Windows error.
To look up the error we need it in decimal format. Start Calculator (Start - All Programs - Accessories - Calculator) and choose View menu - Scientific, then View menu - Hex. Enter 7e. Then View menu - Decimal. It will say 126.
Start a Command Prompt (Start - All Programs - Accessories - Command Prompt) and type
net helpmsg 126
and it will say
The specified module could not be found.
or look it up in winerror.h
//
// MessageId: ERROR_MOD_NOT_FOUND
//
// MessageText:
//
// The specified module could not be found.
//
#define ERROR_MOD_NOT_FOUND 126L
To see what is happening start your program in ntsd.
Start a command prompt.
Type
md c:\symbols
set _NT_SYMBOL_PATH=srv*C:\tmp*http://msdl.microsoft.com/download/symbols;c:\symbols
then (changing it to your program from notepad)
ntsd -g -o c:\windows\notepad.exe
so something
ntsd -g -o wscript "c:\folder\script.vbs"
and wait for the error.

Install inf driver with VBScript on Windows 7

I am trying to write a VBS script that install an USB/Ethernet adapter on Windows 7.
I've got a .INF file for this device.
I first tried:
Dim WshShell, res
Set WshShell = WScript.CreateObject("WScript.Shell")
res = WshShell.Run(WshShell.ExpandEnvironmentStrings( "%SystemRoot%" ) & "\System32\InfDefaultInstall.exe "" C:\Users\Me\Driver.inf """, 1, True)
res equaled 2.
Then I searched another way to do that and I found:
Dim WshShell, res
Set WshShell = WScript.CreateObject("WScript.Shell")
res = WshShell.Run(WshShell.ExpandEnvironmentStrings( "%SystemRoot%" ) & "\System32\rundll32.exe SETUPAPI.DLL,InstallHinfSection DefaultInstall 132 ""Driver.inf""", 1, True)
res equals 0 but I've got an error popup Installation failed.
What's wrong with my code? For the record, the script is launched with administration rights.
EDIT
I've tried to execute the first command directly in prompt and got: The inf file you selected does not support this method of installation..
Nothing happens with second command in prompt.
This is very weird because I can install the driver "manually" when I launch the device manager and select the inf file (with a warning: Windows can't verify the publisher of this driver software.):
Once the driver is installed, the class installer property shows NetCfgx.dll,NetClassInstaller. Could it be used?
I also tried with devcon with no success (program returns devcon.exe failed).
How about this way:
1)If you're using "Windows 7", why not take advantage of the driver pre-staging utility that is built right into the OS? W7 ships with a driver utility called "PNPUTIL". Issuing a command as such will add the drivers:
PNPUTIL -a "X:\Path to Driver File\Driver.inf"
This will process the INF and copy the CAT/SYS/INF (and any DLL, EXE, etc) into the "DriverStore" folder... which is the same place Windows stores all the in-built drivers ready for auto plug-and-play instalaltion.
2)If that's not an option for you, look for "DPInst.exe" (or "DPInst64.exe" for 64-bit systems). These are available as part of the Windows PDK (available free from Microsoft) and will process all INFs in the location you put the file and attempt to pre-stage them. This method tries to copy files to the "Drivers", "CatRoot", and "INF" locations which are not as reliable... and it can occassionally fail to copy required DLLs to "System32" folders etc... but 99% of the time (for simple drivers) it just works. I can arrange to send them to you if you can't find them.
Since I found the option (1) above, that has been my best friend. I use option 2 to isntall Canon USB printers and scanners on our base images, etc... so I know that works too.
I had same problem and solved it by explicitly using ASCII version of InstallHinfSection entry point:
res = WshShell.Run("%Comspec% /C %SystemRoot%\System32\rundll32.exe SETUPAPI.DLL,InstallHinfSectionA DefaultInstall 132 ""Driver.inf""", 1, True)
There is probably a better solution, though (like hinting at the script engine which unicode/ASCII flavor to use).
Also I'm using EN-US system so this workaround may fail on more exotic locales.
Try this:
res = WshShell.Run("%Comspec% /C %SystemRoot%\System32\rundll32.exe SETUPAPI.DLL,InstallHinfSection DefaultInstall 132 ""Driver.inf""", 1, True)

Silent Installation of SQl Express 2005

Can anyone please let me know the procedure to perform silent installation of SQL Server Express 2005 and the way to specify the installation parameters.
Get the MSI and do
string InstallFile = "SSCERuntime-ENU-x86.msi"
string LogFile = "C:\Install.log"
Process proc;
proc = Process.Start("msiexec", "/l " + LogFile + " /quiet /i " + InstallFile);
If you are doing this to support deployment of a desktop application, it's a bad idea.
Use the Compact Edition of SQL Server rather than Express Edition. It's more suited to in-process situations, and it's much easier to deploy.
Thanks for a prompt reply , I would try it ,
but i am loooking something like this for SQL EXPRESS
http://msdn.microsoft.com/en-us/library/ms144259.aspx
You can find the variables here, http://msdn.microsoft.com/en-us/library/ms345154(SQL.90).aspx
You should be able to install silently using msiexec /qn REBOOT=ReallySuppress ADDLOCAL=ALL INSTANCENAME= SAPWD=
You may want to set some other vars that you can find in the above link lik SQLAUTOSTART and DISABLENETWORKPROTOCOLS.

Resources