I'm trying to learn and use PowerShell more, but plenty of other folks I know don't use PowerShell. To allow them to use my scripts I use the following cmd.exe batch file to make it easy to call
PowerShell scripts. To use, just name the batch file name the same as the corresponding PowerShell script filename and put it in the same directory.
@echo off
if "%1"=="/?" goto help
if "%1"=="/h" goto help
if "%1"=="-?" goto help
if "%1"=="-h" goto help
%systemroot%\system32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -Command . %~dpn0.ps1 %*
goto end
:help
%systemroot%\system32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -Command help %~dpn0.ps1 -full
goto end
:end
Additionally for PowerShell scripts that modify the current working directory I use the following batch file:
@echo off
if "%1"=="/?" goto help
if "%1"=="/h" goto help
if "%1"=="-?" goto help
if "%1"=="-h" goto help
%systemroot%\system32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -Command . %~dpn0.ps1 %*;(pwd).Path 1> %temp%\%~n0.tmp 2> nul
set /p newdir=
I used FiddlerCore in GeolocMock to edit HTTPS responses and ran into two stumbling blocks that I'll document here. The first is that I didn't check if the Fiddler root cert existed or was installed, which of course is necessary to edit HTTPS traffic. The following is my code where I check for the certs.
if (!Fiddler.CertMaker.rootCertExists())
{
if (!Fiddler.CertMaker.createRootCert())
{
throw new Exception("Unable to create cert for FiddlerCore.");
}
}
if (!Fiddler.CertMaker.rootCertIsTrusted())
{
if (!Fiddler.CertMaker.trustRootCert())
{
throw new Exception("Unable to install FiddlerCore's cert.");
}
}
The second problem I had (which would have been solved had I read all the sample code first) was that my changes weren't being applied. In my app I only need the BeforeResponse but in order to modify the response I must also sign up for the BeforeRequest event and mark the bBufferResponse flag on the session before the response comes back. For example:
Fiddler.FiddlerApplication.BeforeRequest += new SessionStateHandler(FiddlerApplication_BeforeRequest);
Fiddler.FiddlerApplication.BeforeResponse += new SessionStateHandler(FiddlerApplication_BeforeResponse);
...
private void FiddlerApplication_BeforeRequest(Session oSession)
{
if (IsInterestingSession(oSession))
{
oSession.bBufferResponse = true;
}
}
For my GeolocMock weekend project I intended to use the Bing Maps API to display a map in a WebBrowser control and allow the user to interact with that to select a location to be consumed by my application. Getting my .NET code to talk to the JavaScript in the WebBrowser control was surprisingly easy.
To have .NET execute JavaScript code you can use the InvokeScript method passing the name of the JavaScript function to execute and an object array of parameters to pass:
this.webBrowser2.Document.InvokeScript("onLocationStateChanged",
new object[] {
latitudeTextBoxText,
longitudeTextBoxText,
altitudeTextBoxText,
uncertaintyTextBoxText
});
The other direction, having JavaScript call into .NET is slightly more complicated but still pretty easy as far as language interop goes. The first step is to mark your assembly as ComVisible so that it can interact with JavaScript via COM. VS had already added a ComVisible declaration to my project I just had to change the value to true.
[assembly: ComVisible(true)]
Next set ObjectForScripting attribute to the object you want to expose to JavaScript.
this.webBrowser2.ObjectForScripting = this.locationState;
Now that object is exposed as window.external in JavaScript and you can call methods on it.
window.external.Set(lat, long, alt, gUncert);
However you don't seem to be able to test for the existence of methods off of it. For example the following JavaScript generates an exception for me even though I have a Set method:
if (window.external && window.external.Set) {
Working on GeolocMock it took me a bit to realize why my HTML could use the W3C Geolocation API in IE9 but not in my WebBrowser control in my .NET application. Eventually I realized that I was getting the wrong IE doc mode. Reading this old More IE8 Extensibility Improvements IE blog post from the IE blog I found the issue is that for app compat the WebOC picks older doc modes but an app hosting the WebOC can set a regkey to get different doc modes. The IE9 mode isn't listed in that article but I took a guess based on the values there and the decimal value 9999 gets my app IE9 mode. The following is the code I run in my application to set its regkey so that my app can get the IE9 doc mode and use the geolocation API.
static private void UseIE9DocMode()
{
RegistryKey key = null;
try
{
key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", true);
}
catch (Exception)
{
key = Registry.CurrentUser.CreateSubKey("Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION");
}
key.SetValue(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName, 9999, RegistryValueKind.DWord);
key.Close();
}
I've made GeolocMock. If your PC has no geolocation devices, IE9 uses a webservice to determine your location. GeolocMock uses FiddlerCore to intercept the response from the webservice and allows the user to replace the location in the response with another. This was a fun weekend project in order to play with FiddlerCore, the W3C Geoloc APIs in IE9, hosting the IE9 WebOC in a .NET app, and the Bing Maps APIs.
I've made two simple command line tools related to the console window and Win7 jump lists. The source is available for both but neither is much more than the sort of samples you'd find on MSDN =).
SetAppUserModelId lets you change the Application User Model ID for the current console window. The AppUserModelId is the value Win7 uses to group together icons on the task bar and is what the task bar's jump lists are associated with. The tool lets you change that as well as the icon and name that appear in the task bar for the window, and the command to launch if the user attempts to re-launch the application from its task bar icon.
SetJumpList lets you set the jump list associated with a particular AppUserModelId. You pass the AppUserModelId as the only parameter and then in its standard input you give it lines specifying items that should appear in the jump list and what to execute when those items are picked.
I put these together to make my build environment easier to deal with at work. I have to deal with multiple enlistments in many different branches and so I wrote a simple script around these two tools to group my build windows by branch name in the task bar, and to add the history of commands I've used to launch the build environment console windows to the jump list of each.
For a new project I'm working on involving IE's installed Accelerators and OpenSearch search providers via the Windows 7 Accelerator Platform, I've created a C#/COM interop class for those APIs.
Download the osinterop.cs interop file here.
I've just got a new media center PC connected directly to my television with lots of HD space and so I'm ripping a bunch of my DVDs to the PC so I don't have to fuss with the physical media. I'm ripping with DVD Rip, viewing the results in Windows 7's Windows Media Center after turning on the WMC DVD Library, and using a powershell script I wrote to copy over cover art and metadata.
My powershell script follows. To use it you must do the following:
Download copydvdinfo.ps1