Disclaimer: I wrote this over 10 years ago, so its a little rough. But I was reminded about this recently and wanted to reshare it. Enjoy.
It's been a while since I have had time to post anything of interest to me but I wanted to share a little bit of information I stumbled across a few days ago. The situation required a log on script to change screen resolution to a pre-defined size. How would I accomplish this task without using a program like qres or reso and make a script to do it?
I like PowerShell scripts because it seems to do just about anything on a Windows pc. After a short search I turned towards a resource that has been a great resource in my personal PowerShell journey, Microsoft's "Hey, Scripting Guy!" blog & Script Center. I found an interesting article from two years ago asking the very same question I had, with an interesting answer, and a example that at first wasn't clear to me how it worked. I plan to explain it in a way that may help other's still learning PowerShell.After reading the "Hey, Scripting Guy!" blog entry from July 7th, 2010 I copied and pasted the code into my favorite text editor, notepad++ , and began to analyze the code. What was scripted by Andy Schneider was exactly what I had been looking for!
I wrote this original article back in 2012, the link is lost (or appears to be) but seems to survive on PastBin.com. I went ahead and put the copy/paste here for reference.
Function Set-ScreenResolution {
<#
.Synopsis
Sets the Screen Resolution of the primary monitor
.Description
Uses Pinvoke and ChangeDisplaySettings Win32API to make the change
.Example
Set-ScreenResolution -Width 1024 -Height 768 -Freq 60
#>
param (
[Parameter(Mandatory=$true,
Position = 0)]
[int]
$Width,
[Parameter(Mandatory=$true,
Position = 1)]
[int]
$Height,
[Parameter(Mandatory=$true,
Position = 2)]
[int]
$Freq
)
$pinvokeCode = @"
using System;
using System.Runtime.InteropServices;
namespace Resolution
{
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE1
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
};
class User_32
{
[DllImport("user32.dll")]
public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE1 devMode);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettings(ref DEVMODE1 devMode, int flags);
public const int ENUM_CURRENT_SETTINGS = -1;
public const int CDS_UPDATEREGISTRY = 0x01;
public const int CDS_TEST = 0x02;
public const int DISP_CHANGE_SUCCESSFUL = 0;
public const int DISP_CHANGE_RESTART = 1;
public const int DISP_CHANGE_FAILED = -1;
}
public class PrmaryScreenResolution
{
static public string ChangeResolution(int width, int height, int freq)
{
DEVMODE1 dm = GetDevMode1();
if (0 != User_32.EnumDisplaySettings(null, User_32.ENUM_CURRENT_SETTINGS, ref dm))
{
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
dm.dmDisplayFrequency = freq;
int iRet = User_32.ChangeDisplaySettings(ref dm, User_32.CDS_TEST);
if (iRet == User_32.DISP_CHANGE_FAILED)
{
return "Unable to process your request. Sorry for this inconvenience.";
}
else
{
iRet = User_32.ChangeDisplaySettings(ref dm, User_32.CDS_UPDATEREGISTRY);
switch (iRet)
{
case User_32.DISP_CHANGE_SUCCESSFUL:
{
return "Success";
}
case User_32.DISP_CHANGE_RESTART:
{
return "You need to reboot for the change to happen.\n If you feel any problems after rebooting your machine\nThen try to change resolution in Safe Mode.";
}
default:
{
return "Failed to change the resolution";
}
}
}
}
else
{
return "Failed to change the resolution.";
}
}
private static DEVMODE1 GetDevMode1()
{
DEVMODE1 dm = new DEVMODE1();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
return dm;
}
}
}
"@
Add-Type $pinvokeCode -ErrorAction SilentlyContinue
[Resolution.PrmaryScreenResolution]::ChangeResolution($width,$height,$freq)
}
Set-ScreenResolution -Width 1920 -Height 1080 -Freq 60
Here's where I screwed up at first; I didn't catch that the copied code was essentially a custom PowerShell function that needs to be called upon when loaded at the powershell command prompt. If you remove the "Function Set-ScreenResolution" and curly braces from the top and bottom of the script, you will get a simple GUI asking for resolution parameters.
I have outlined the steps below with screenshots to create a PowerShell script that calls this custom function and based on your input, will change your screen resolution.
1. Create a folder in a location of your choosing and call it "ScreenResolution" or whatever you choose.
2. Using your favorite PowerShell editor (I used both notepad++ and PowerShell ISE), copy and paste the code example from Andy Schneider listed in the above "Hey, Scripting Guy!" post from July 7th, 2010 into your new .ps1 file. Save this function as "Set-ScreenResolution.ps1" .
3. Open a new tab in your powershell editor, and use my example PowerShell script below:
# Load Set-ScreenResolution function
. .\Set-ScreenResolution.ps1
# Run the function
Set-ScreenResolution 1024 768
Save this script. I chose 1024x768.ps1 to identify the resolution the script would set as my resolution.
*Notice the . before the path to our function. This loads the function before executing the command with parameters. This is where I had some trouble at first, thought I would note it. For more information on Functions, here's a good start: http://www.powershellpro.com/powershell-tutorial-introduction/powershell-functions-filters/
4. Open a PowerShell prompt and cd to your folder location. In my example, I chose C:\ScreenResolution\.
All that's left is to type in the name of your resolution PowerShell script containing your set parameters and voila! screen resolution changes! You can also right click on the script and choose "Run with PowerShell".
I hope this helps those like me who are not programmers but enjoy learning and using PowerShell. I would also like to say thank you to the whole "Hey, Scripting Guy!" team for the original blog post about this topic.
You can see all my old ramblings when I was a wee little blogger over at the now deprecated Bill's Tech Ramblings (kindleit.blogspot.com)