Someone asked in the #PowerShell channel on FreeNode for a way to register dll’s (you know, old COM libraries for use in scripts or apps) ... specifically, they wanted to create a script that could register a bunch of Dll files, and know which ones passed or failed.
It turned out to be an interesting problem, because even though the source code on the MSDN Library has a /C parameter to cause the application to write to stdout, the one which comes with windows doesn’t, so the only obvious way to get output is in a MessageBox. However, there is also an exit code, but the exit code doesn’t seem to end up in $LASTEXITCODE or $? at all (maybe because the app is actually not a console app? I don’t get it, really). So the real problem became: how do I capture the exit code of an application in PowerShell?
[new] Someone sent me an email today (Jan 7 2010) mentioning that if you nest your call to regsvr32 inside a call to cmd.exe … it does set the $LastExitCode:
cmd /c "regsvr32 /s 'C:\Path\To\Some.dll'"
$LastExitCode ## Will be set correctly.
Well, the simplest thing would be to just go around that — to compile and distribute the MSDN sample with the /c console output option so I don’t need the exit code. Of course, they are very clear that we shouldn’t do that because the sample isn’t “safe,” and distributing it afterward would probably be a problem with licensing. Well, I don’t know about that, but I figured the best thing would be to just use the exit code from the existing RegSvr32.exe rather than asking people to use what they would perceive as a 3rd party RegSvr32.
And if we play around a bit with the .Net Process and ProcessStartInfo classes, it’s not to hard to get the exit code …
After a bit more experimentation with the return values, I came up with a function called RegisterDllServer which appears below. The function has a -Verbose switch and a -Debug switch which turn on some helpful messages (the Debug switch actually allows the RegSvr32 message boxes to show up, so you shouldn’t use that if you’re calling it from within a script).
So, to answer the original question, to use this to register all the dll’s in a folder you could just call it like ls *.dll | RegSvr32 using the alias that the script sets up at the end, or to be more complete, call it like: ls *.dll | % {$r=$(RegSvr $_); if($r -gt 0){ "FAILED: $_" } else { "SUCCEEDED: $_" }} … nice, eh?
I’m just getting into PowerShell, but this seems like a lot of work compared with the old cmd.exe way of achieving the same thing
C:\> for %i in (*.dll) do regsvr32 /s %i
Calling regsvr32 with the /s silent switch does not do anywhere near the same thing — it just hides the message box entirely — you would have no idea if it worked or not. You could, of course, do that in PowerShell:
The script I provided doesn’t have any pop-up MessageBoxes, but it does provide the results, including the appropriate error messages as console output, so you would know whether the registration succeeded or not, and if not, why.
Thanks for the clarification Joel, I guessed I was missing something, but didn’t appreciate the subtlety of actually being able to access the return code
Ah, but you can test the return code of regsvr32, for example it returns 3 if the file doesn’t exist
Peter: what do mean? Yes, of course you can test the return code — that’s the whole point of this script…