InstallShield Automation can't create object - powershell

I am working with Installshield 2014 and 2011. I'm using major upgrades and automated build scripts to handle the build. InstallShield is the stand alone build ver. for both.
Now everything worked fine with Installshield 2011 on windows 2003 servers. I could use the automation interface to open a project, change the product code (for the major upgrade) then save it right before building the installer.
The code for such is in a vbs file as such:
Dim oISM, oGUID
Set oGUID = CreateObject("InstallShield.GUID")
Set oISM = CreateObject("IswiAuto17.ISWiProject")
oISM.OpenProject strInstallShieldProjectFile
oISM.ProductCode = "{" & oGUID.CreateGUID( ) & "}"
oISM.SaveProject : oISM.CloseProject : set oISM = Nothing
Now we've upgraded to windows 2012 servers and InstallShield 2014. I've double checked and according to InstallShield the only change needed is the ver number (17 changes to 21).
But now nothing works. If I take the code out and put it in it's own vbs file for testing and run it, I get this:
ActiveX component can't create object: 'InstallShield.GUID'
Looking on google I see that's from running in 64 bit mode.... but I'm not. I'm running a cmd prompt in 32 bit mode.
http://helpnet.flexerasoftware.com/installshield18helplib/AutomationInterface64Bit.htm
I tried calling the script with:
%WINDIR%\SYSWOW64\cmd.exe /c cscript
as suggested here:
How do I run a VBScript in 32-bit mode on a 64-bit machine?
and other places. This did not work as I got the same error.
I tried removing that line as I'm sure I can create a guid another way, and reran it.
Then I got this when it tries to create the project:
Unknown runtime error: 'CreateObject'
Once again google came up and I checked:
https://community.flexerasoftware.com/showthread.php?189788-Automation-error
and couple others. I tried ensuring the dll was registered using the regsvr32 and it said it was successful. But after rerunning, it gave the same error.
I tried directly coping the command from the InstallShield documentation to ensure no spelling mistakes but again same error.
I even tried switching the case of the "sw" as mentioned here:
Installshield Automation is failing while running vbscript with error unable to create object
Again though, same error.
I also tried switching to powershell as powershell is much easier to debug and read.
The powershell code is simple and is as follows:
$oIsm = new-object -comobject IswiAuto21.ISWiProject
$oISM.OpenProject("$file")
$oISM.ProductCode = "{" + [guid]::NewGuid() + "}"
$oISM.SaveProject(); $oISM.CloseProject(); $oISM = $null
But this also does not work despite these saying it should:
https://community.flexerasoftware.com/showthread.php?190769-Automation-using-Powershell
http://blogs.flexerasoftware.com/installtalk/2011/01/getting-started-with-installshield-automation-and-powershell.html
When I use the 32 bit powershell I get this error:
new-object : Creating an instance of the COM component with CLSID {78D393F9-76E3-438C-9CAB-6664EF5FE1F2} from the IClassFactory failed due to the following error:
800a801d Exception from HRESULT: 0x800A801D.
If I run solely the vbs without a cmd prompt I also see the error of 800A801D in a pop up box.
How can I fix this? I'd like to use powershell but a vbs fix would help as well at this point. I have tried everything I can think of and google says I'm doing it correctly (32 bit powershell/cmd, registering the dll, creating the object, etc).

Did you install the automation interface? Typically it's an optional feature that's set to absent when you install InstallShield.

Typically the HRESULT should tell you what's wrong, or be so generic that it doesn't help. In this case, it's a bit of an enigma as I haven't found its definition anywhere. The leading 0x800A... indicates FACILITY_CONTROL and the trailing ...801d happens to match the tail of TYPE_E_LIBNOTREGISTERED (0x8002801D), but I don't know whether that's meaningful. Unfortunately FACILITY_CONTROL is defined by the control that issues the error, and that's not clear here.
Let's try to figure out what's wrong. My bet is on COM registration. If you want, you can skip to a likely fix by running regsvr32 C:\...\System\ISWiAutomation21.dll.
So let's follow what CreateObject("IswiAuto21.ISWiProject") will do. First it has to look up the ProgID:
C:\>reg query HKCR\ISWiAuto21.ISWiProject\Clsid
HKEY_CLASSES_ROOT\ISWiAuto21.ISWiProject\Clsid
(Default) REG_SZ {78D393F9-76E3-438C-9CAB-6664EF5FE1F2}
Then it has to look up the CLSID, and in this case, its InprocServer32 key:
C:\>reg query HKCR\Clsid\{78D393F9-76E3-438C-9CAB-6664EF5FE1F2}\InprocServer32
HKEY_CLASSES_ROOT\Clsid\{78D393F9-76E3-438C-9CAB-6664EF5FE1F2}\InprocServer32
(Default) REG_SZ C:\...\ISWiAutomation21.dll
ThreadingModel REG_SZ Apartment
If either of these are missing, it will be unable to find the COM server. In addition, the TypeLib subkey and the Type Library it references are both important:
C:\>reg query HKCR\Clsid\{78D393F9-76E3-438C-9CAB-6664EF5FE1F2}\Typelib
HKEY_CLASSES_ROOT\Clsid\{78D393F9-76E3-438C-9CAB-6664EF5FE1F2}\Typelib
(Default) REG_SZ {92278CC1-987E-4A01-940C-47DCADF27496}
C:\>reg query HKCR\Typelib\{92278CC1-987E-4A01-940C-47DCADF27496}\1.1\0\win32
HKEY_CLASSES_ROOT\Typelib\{92278CC1-987E-4A01-940C-47DCADF27496}\1.1\0\win32
(Default) REG_SZ C:\...\ISWiAutomation21.dll
If any of this information is missing, it will have to be repaired. The COM Server itself may need to probe several additional IDs at this point, so there's a chance that even if this subset is okay, there are others that are missing or corrupted. Self-registering the COM server should fix this. So should running the installation's repair.
Note that all of these queries were done using the 32-bit command C:\Windows\SysWow64\reg.exe, or you can peruse the registry visually with C:\Windows\SysWow64\regedit.exe.

Related

How to run powershell quietly from registry key?

I've added an option to copy a proper UNC path to the context menu of all directories via PowerShell.
Edit:
I didn't mention that I'm actually using two different keys: One to copy the UNC of the current directory, and one to copy it from a different directory. I didn't think it would make a difference, but it does.
End Edit
Currently, the key value is as follows:
powershell.exe -WindowStyle Hidden -Command . <path I have to censor>\Save-To-Clipboard.ps1 \"%L%\"
Expected behaviour:
The PowerShell script is run quietly.
Actual behaviour:
A PowerShell Window pops up and closes itself.
The same thing happens with cmd.
I've tried using a VBS wrapper as well, but it needs the current path as an argument, which I can't figure out how to do. Simply putting it after the filename as you would in the command line results in the error:
This file does not have an app associated with it for performing this
action. Please install an app or, if one is already installed, create
an association in the Default Apps settings page.
Key value here:
<path I have to censor>\ClunkyWrapper.vbs \"%L%\"
Admittedly, this is my first time running a command from a registry key, and I can't seem to find any resources about this topic. (I might just not know what exactly to google for.) So I would be thankful for more general information on how to run commands from registry keys as well.
Okay, I found a way.
First of all, apparently whether you need to use %L% or %V% depends on the key. I can't tell you why, unfortunately.
That solves the error message of the VBA script, but it still wouldn't run like this.
So I then used wscript.exe, and it finally worked.
wscript.exe <secret path>\ClunkyWrapper.vbs "%V%"

NSIS nsProcess Plugin: Always returns "process not running"

Context
We are using NSIS 3.05 with Unicode true (this is important later).
We need to check if a certain process is running, let's call it "processToFind.exe".
In order to do that, we have been using nsProcess Plugin, which is set up correctly, found and integrated just fine.
We include Plugins from our git repository like this:
!addincludedir "C:\pathToRepo\NSIS\Include"
!addplugindir "C:\pathToRepo\NSIS\Plugins"
where pathToRepo is of course a valid path. We also tried using the default Plugin Directories (NSIS-Dir\Plugins\x86-unicode) to no avail (see below).
Documentation says, nsProcess (v 1.6) does suppport unicode. That's why we chose to use it.
NSIS UNICODE support (just rename nsProcessW.dll into nsProcess.dll)
When setting Unicode false or leaving the setting out (so default is ansi), it is working fine, too. ( = running processes found, not running processes not found )
The Installer is 32 bit, we are running on 64 bit Windows 10 machines.
Code
${nsProcess::FindProcess} "procexp.exe" $R0
MessageBox MB_OK "procexp: [$R0]"
which is defined in nsProcess.nsh (provided by plugin, not own code)
!define nsProcess::FindProcess `!insertmacro nsProcess::FindProcess`
!macro nsProcess::FindProcess _FILE _ERR
nsProcess::_FindProcess /NOUNLOAD `${_FILE}`
Pop ${_ERR}
!macroend
Problem
When having set Unicode true , nsProcess will always return 603 ("Process was not currently running").
That's the same, regardless if we try to find 32-bit or 64-bit processes.
That would be expected for 64-bit processes (they cannot be found from 32-bit installers, which is ok for us).
But I do expect it to find 32-bit processes.
Alternatives already explored:
Going through the list found at Check whether your application is running ...
Processes Plugin : Seems outdated, only sourcecode found.
"FindProcess.nsh" : Naming collision, didn't work, neither. Same symptoms.
DDE Server / Win32 Sync / Registry: Not an option.
"tasklist" command: Same symptoms. When executed in cmd, it works but not from installer.
nsExec::ExecToStack '"%SystemRoot%\System32\tasklist" /NH /FI "IMAGENAME eq ${processName}" | "%SystemRoot%\System32\find" /I "${processName}"' always returns "error". (* it's clear now why, see edit below)
"FindProcDLL" Plugin : skipped because
As of NSIS 2.46 this plugin no longer works...
Seemingly related Stackoverflow Questions explored:
NSIS : NsProcess UnExpected Output
Solution was to remove Unicode=true, which I cannot do.
NSIS- FindProc always returns 1
Uses FindProcDLL
NSIS - check if process exists (nsProcess not working)
Error was "Plugin not found" , which we do not have.
I am sure, we are making some "stupid" mistake since I cannot bring myself to believing we are the only ones with that requirement. So, any hints, suggestions and alternatives that are not listed above (or corrections to the above) are welcomed.
Edit
We totally messed up the tasklist call. As #Anders pointed out in comment: nsExec does not support pipes and on top of that, the syntax was also messed up.
Does official example work for you? It works on my machine.
Try this:
0) Delete all nsProcess.dll files (in NSIS, in your include folders, everywhere)
1) Remove line !addplugindir "C:\pathToRepo\NSIS\Plugins" from your script to use plugins in NSIS directories
2) Copy file nsProcessW.dll into **c:\Program Files (x86)\NSIS\Plugins\x86-unicode**
3) Rename file c:\Program Files (x86)\NSIS\Plugins\x86-unicode\nsProcessW.dll -> nsProcess.dll
4) Compile your script with Unicode true
I believe there is some file mismatch. To understand NSIS plugins structure see NSIS - check if process exists (nsProcess not working) .
I'm still using ANSI because I'm using some other plugins that don't have a Unicode variant, so nsProcess works for me, and I'm not sure how to answer your main question.
However, re: the tasklist command alternative you listed, the syntax isn't quite right. You're missing a closing quote after "IMAGENAME eq ${processName}["] and an opening quote before ["]${processName}" in the pipe to find.exe.
Also FYI note that if you use %SystemRoot%\System32\, a 32-bit process will be redirected to C:\Windows\SysWOW64\, and some programs have no 32-bit equivalent (e.g., pnputil). In this case, it doesn't really matter, but in any event to get around this, you should use $WINDIR\SysNative instead. You can also use ${DisableX64FSRedirection} from x64.nsh, but there are apparently some potential pitfalls there.
EDIT: Ah yes, and there's the issue with pipe and ExecToStack mentioned by Anders in the comments to the original question, requiring the call to be prefixed with cmd.exe /C

PowerShell can't "dot source" profile following system cleaning

I have a problem where PowerShell will no longer run my Microsoft.Powershell_profile.ps1/Profile.ps1 script stating it can't "dot source" the file. This started after I ran a registry cleaner and system optimizer on my machine. Now, I can't figure out what setting has changed, been added, or revoked.
Things to note:
The console always defaults to 'ConstrainedLanguage' because of the attempt to "dot source"
I have tried setting the -ExecutionPolicy to both "Unrestricted" and "RemoteSigned" to no effect
Issue exists in both version 5 & 6
If I run the "PowerShell Integrated Console" in VS Code, as opposed to in the terminal window, it runs fine showing "FullLanguage"
The contents of the profile file do not matter - if I use an empty file, it still won't run.
Placing "Microsoft.Powershell_profile.ps1" in the "\documents" folder does NOT produce a "dot source" error, however it also doesn't recognize any commands from within the profile script.
Things I have tried:
Setting to "FullLanguage" via $ExecutionContext.SessionState.LanguageMode = 0 results in "Cannot set property. Property setting is supported only on core types in this language mode."
Setting the "__PSLockdownPolicy" property to 0 in the registry at "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\" does nothing for v5 and crashes v6
Moving the profile file between $home, "\documents", and $pshome (location dependent on version) to no effect (with the above exception)
Adjusting name between "Microsoft.Powershell_profile.ps1" and "Profile.ps1" (normally adjusted to match intended audience ("All Users", for example) but am trying variations in hopes of making work)
Uninstalling and re-installing different 5.x and 6.x versions to no effect
Running "Powershell -noprofile" doesn't load the profile, so no error but still runs in "ConstrainedLanguage"
Verified AppLocker is not running / has not rules in place
Verified Controlled Folder Access is off
Any help would be appreciated.

SCCM PowerShell Get Configuration Baseline computers

I am working with Configuration Baselines. I would like to start from "Get-CMBaseline -Name MyBaselineName" and work my way to the name of the machines. I am try to figure out how to get the machines names that are "Compliant", "Error", and "Non-Compliant". I see the names of the machines in "Deployment Status" but I need them via PowerShell.
There are many things that are possible via the built in cmdlets but some just are not (yet?). However it is almost always possible to get the same behavior the console has with wmi (because the console uses wmi itself)
To find out how it is good to know that there is a log file "SMSProv.log" that tells you what the console does for every dialog you open. It is located on the site server wherever you installed the ConfigMgr in a sub-folder Logs (so default would be %Program Files%\Microsoft Configuration Manager\Logs).
So if you use that when checking the deployment status of a baseline you will notice that it basically translates to 3 commands (All in the namespace
Root\SMS\site_<SiteCode>
on your siteserver):
SELECT * FROM SMS_DCMDeploymentCompliantAssetDetails WHERE AssignmentID=<AssignmentID>
SELECT * FROM SMS_DCMDeploymentNonCompliantAssetDetails WHERE AssignmentID=<AssignmentID>
SELECT * FROM SMS_DCMDeploymentErrorAssetDetails WHERE AssignmentID=<AssignmentID>
where AssignemtID is the ID you would get e.g. from
(Get-CMBaselineDeployment -Name "<Your Baslines Name>").AssignmentID
A little exception would be that the console filters the error further by error type but to me it seems like this is maybe not even what you want and you could easily do it in Powershell later if you need to.
The SQL command is also available in most cases in the SMSProv.log, and in some cases it leads to a faster execution. However in this one probably not really and it is a lot more complex most of the time.

PowerShell: Start-Process Firefox, how do he know the path?

When I call the following code:
Start-Process Firefox
Then the PowerShell opens the browser. I can do that with several other programs and it works. My question is: How does the PowerShell know which program to open if I type Firefox? I mean, Im not using a concrete Path or something ...
I though it has something to do with the environment variables ... But I cannot find any variable there which is called Firefox ... How can he know?
I traced two halves of it, but I can't make them meet in the middle.
Process Monitor shows it checks the PATHs, and eventually checks HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe so that's my answer to how it finds the install location, and then runs it.
That registry key is for Application Registration which says:
When the ShellExecuteEx function is called with the name of an executable file in its lpFile parameter, there are several places where the function looks for the file. We recommend registering your application in the App Paths registry subkey.
The file is sought in the following locations:
The current working directory.
The Windows directory only (no subdirectories are searched).
The Windows\System32 directory.
Directories listed in the PATH environment variable.
Recommended: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
That implies PowerShell calls the Windows ShellExecuteEx function, which finds FireFox as a registered application, or it tries the same kind of searching itself internally.
Going the other way to try and confirm that, the Start-Process cmdlet has a parameter set called UseShellExecute. The 'Notes' of that help says:
This cmdlet is implemented by using the Start method of the System.Diagnostics.Process class. For more information about this method, see Process.Start Method
Trying to trace through the source code on GitHub:
Here is the PowerShell source code for Start-Process.
Here, at this line it tries to look up the $FilePath parameter with CommandDiscovery.LookupCommandInfo.
Here it checks else if (ParameterSetName.Equals("UseShellExecute"))
Then Here is the .Start() function which either starts it with ShellExecute or Process.Start()
OK, not sure if ShellExecute and ShellExecuteEx behave the same, but it could be PS calling Windows, which is doing the search for "FireFox".
That CommandSearcher.LookupCommandInfo comes in here and follows to TryNormalSearch() which is implemented here and immediately starts a CommandSearcher which has a state machine for the things it will search
SearchState.SearchingAliases
Functions
CmdLets
SearchingBuiltinScripts
StartSearchingForExternalCommands
PowerShellPathResolution
QualifiedFileSystemPath
and there I get lost. I can't follow it any further right now.
Either it shortcuts straight to Windows doing the lookup
Or the PowerShell CommandSearcher does the same search somehow
Or the PowerShell CommandSearcher in some way runs out of searching, and the whole thing falls back to asking Windows search.
The fact that Process Monitor only logs one query in each PATH folder for "firefox.*" and then goes to the registry key suggests it's not doing this one, or I'd expect many more lookups.
The fact that it logs one query for "get-firefox.*" in each PATH folder suggests it is PowerShell's command searcher doing the lookup and not Windows.
Hmm.
Using Process Monitor I was able to trace the PowerShell.
It first searches the $env:path variable, then the $profile variable.
In my case firefox wasn't found and then it searches through a whole lot in the Registry and somehow finds it.
It might have something to do with how firefox is installed on the system.