C# Printing Reports with dot matrix printer - c#

I have dot matrix printer, but when I print it some of the characters doesn't accept, like degrees(°), diameter(Ø), number with power of two(2²) and etc. Take a look at the photos.
EXAMPLE OUTPUT
When printing it shows a black SQUARE.
This is the line code.
MyPrinter.Print((char)15 + " itemname.Text " + "\r\n");
This is the Class code
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)] public string pDocName;
[MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)] public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
/*=================================================*/
private IntPtr HandlePrinter;
public PrinterSettings ps;
public LPrinter()
{
HandlePrinter = IntPtr.Zero;
ps = new PrinterSettings();
}
public PrintDialog pd = new PrintDialog();
public string PrinterName
{
get
{
return ps.PrinterName;
}
set
{
ps.PrinterName = value;
}
}
public bool Open(string DocName)
{
// see if printer is already open
if (HandlePrinter != IntPtr.Zero) return false;
// opens the printer
bool risp = OpenPrinter(ps.PrinterName, out HandlePrinter, IntPtr.Zero);
if (risp == false) return false;
// starts a print job
DOCINFOA MyDocInfo = new DOCINFOA();
MyDocInfo.pDocName = DocName;
MyDocInfo.pOutputFile = null;
MyDocInfo.pDataType = "RAW";
if (StartDocPrinter(HandlePrinter, 1, MyDocInfo))
{
StartPagePrinter(HandlePrinter); //starts a page
return true;
}
else return false;
}
public bool Close()
{
if (HandlePrinter == IntPtr.Zero) return false;
if (!EndPagePrinter(HandlePrinter)) return false;
if (!EndDocPrinter(HandlePrinter)) return false;
if (!ClosePrinter(HandlePrinter)) return false;
HandlePrinter = IntPtr.Zero;
return true;
}
public bool Print(string outputstring)
{
if (HandlePrinter == IntPtr.Zero) return false;
IntPtr buf = Marshal.StringToCoTaskMemAnsi(outputstring);
Int32 done = 0;
bool ok = WritePrinter(HandlePrinter, buf, outputstring.Length, out done);
Marshal.FreeCoTaskMem(buf);
if (!ok) return false;
else return true;
}
Hope someone can help me to fix this.

Related

Wpf - .Net Core 3.1 - Get all opened process window preview image and display

Currently I'm developing a project that needs to show a preview image of all opened process and display it on a grid.
Exactly like Microsoft Teams shows when you try to select a window to be shared.
So far I've achive the following design
Which is mounted using the following code:
private void CreateOpenedWindowsMenuItems(IEnumerable<CapturableWindow> openedWindows)
{
var dataGridRowNumber = 0;
var dataGridRowColumnNumber = 0;
CreateNewRowDefinition();
foreach (var openedWindow in openedWindows)
{
if (dataGridRowColumnNumber == MaxItemsPerRow)
dataGridRowColumnNumber = AddNewRowToGrid(ref dataGridRowNumber);
var openedWindowCard = CreateCard(CardSize);
var selectItemCheckbox = new CheckBox { IsEnabled = false, Margin = new Thickness(5,0,0,0)};
var openedWindowCardStackPanel = CreateStackPanel(openedWindow, selectItemCheckbox);
openedWindowCard.Content = openedWindowCardStackPanel;
openedWindowCard.MouseLeftButtonDown += (sender, args) =>
{
if (selectItemCheckbox.IsChecked == true)
_capturedWindows.Remove(openedWindow);
else
_capturedWindows.Add(openedWindow);
selectItemCheckbox.IsChecked = !selectItemCheckbox.IsChecked;
};
Grid.SetRow(openedWindowCard, dataGridRowNumber);
Grid.SetColumn(openedWindowCard, dataGridRowColumnNumber);
AvailableCapturableWindows.Children.Add(openedWindowCard);
dataGridRowColumnNumber++;
}
}
private StackPanel CreateStackPanel(CapturableWindow window, CheckBox selectItemCheckbox)
{
var stackPanel = new StackPanel();
var textStackPanel = new StackPanel { Orientation = Orientation.Horizontal };
textStackPanel.Children.Add(new TextBlock
{
Text = $"{window.Name.Substring(0, 25)}...",
TextWrapping = TextWrapping.NoWrap,
TextAlignment = TextAlignment.Center,
FontSize = 10,
FontWeight = FontWeights.Bold,
Foreground = new SolidColorBrush(Colors.White),
});
textStackPanel.Children.Add(selectItemCheckbox);
stackPanel.Children.Add(textStackPanel);
var previewImage = CreatePreviewImage(window.Handle);
if (previewImage != null) stackPanel.Children.Add(previewImage);
return stackPanel;
}
private UIElement CreatePreviewImage(IntPtr hWnd)
{
try
{
var handle = hWnd;
if (!NativeMethods.IsWindow(handle))
return null;
var hdcSrc = NativeMethods.GetWindowDC(handle);
NativeMethods.GetWindowRect(handle, out var windowRect);
var width = windowRect.Right - windowRect.Left;
var height = windowRect.Bottom - windowRect.Top;
var hdcDest = NativeMethods.CreateCompatibleDC(hdcSrc);
var hBitmap = NativeMethods.CreateCompatibleBitmap(hdcSrc, width, height);
var hOld = NativeMethods.SelectObject(hdcDest, hBitmap);
var bRet = NativeMethods.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, NativeMethods.SRCCOPY);
NativeMethods.SelectObject(hdcDest, hOld);
NativeMethods.DeleteDC(hdcDest);
NativeMethods.ReleaseDC(handle, hdcSrc);
var imageSource = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
return new Image { Source = imageSource, VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center };
}
catch (Exception)
{
return new PackIcon { Kind = PackIconKind.Image };
}
}
private static Card CreateCard(int cardSize)
{
var card = new Card
{
Width = cardSize,
Height = cardSize,
VerticalAlignment = VerticalAlignment.Center,
HorizontalContentAlignment = HorizontalAlignment.Center,
Margin = new Thickness(10),
Cursor = Cursors.Hand
};
card.MouseEnter += (sender, args) =>
{
card.Width = CardSizeHovered;
card.Height = CardSizeHovered;
};
card.MouseLeave += (sender, args) =>
{
card.Width = cardSize;
card.Height = cardSize;
};
return card;
}
private int AddNewRowToGrid(ref int dataGridRowNumber)
{
dataGridRowNumber++;
CreateNewRowDefinition();
return InitialColumnItemNumber;
}
private void CreateNewRowDefinition()
{
AvailableCapturableWindows.RowDefinitions.Add(new RowDefinition { Height = new GridLength(256) });
}
I also have a NativeMethods Class:
public static class NativeMethods
{
public const int SRCCOPY = 0x00CC0020;
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, int nFlags);
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hg);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("gdi32.dll")]
public static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll")]
public static extern int BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int rop);
[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("d3d11.dll", EntryPoint = "CreateDirect3D11DeviceFromDXGIDevice", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern uint CreateDirect3D11DeviceFromDXGIDevice(IntPtr dxgiDevice, out IntPtr graphicsDevice);
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
public static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
public static IntPtr GetActiveWindow() => GetForegroundWindow();
[DllImport("CoreMessaging.dll", EntryPoint = "CreateDispatcherQueueController", SetLastError = true, CharSet = CharSet.Unicode,ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern uint CreateDispatcherQueueController(DispatcherQueueOptions options, out IntPtr dispatcherQueueController);
}
How can i get the preview window image, and use It in my card element, after the window text name,based on IntPtr?

StartDocPrinter failing (ERROR_INSUFFICIENT_BUFFER)

I'm trying to open a raw printer connection and the StartDocPrinter call is failing. Win32Error is 122 (ERROR_INSUFFICIENT_BUFFER).
This executable works fine on the same computer when run as a normal user or as administrator, but fails when run as the "local system" user. (Though I've had it work on several other computers running as the "local system" user.) I really don't want to consider running it as a different user, since it's running through a service and would probably involve several other large changes to the system.
using System;
using System.Runtime.InteropServices;
namespace EPLTest
{
class Program
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)]
public string pDocName;
[MarshalAs(UnmanagedType.LPStr)]
public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)]
public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
static void Main(string[] args)
{
IntPtr hPrinter;
if (!OpenPrinter("ZDesigner LP2824 Raw".Normalize(), out hPrinter, IntPtr.Zero))
{
Console.WriteLine("OpenPrinter Error:" + Marshal.GetLastWin32Error());
return;
}
Console.WriteLine("hPrinter: " + hPrinter.ToString("x8"));
DOCINFOA di = new DOCINFOA { pDocName = "Barcode Test", pDataType = "RAW" };
if (StartDocPrinter(hPrinter, 1, di))
{
Console.WriteLine("StartDocPrinter Success");
// Printing code omitted for brevity
EndDocPrinter(hPrinter);
}
else
{
Console.WriteLine("StartDocPrinter Error:" + Marshal.GetLastWin32Error());
}
ClosePrinter(hPrinter);
}
}
}
Sample output:
hPrinter: 010b7e3c
StartDocPrinter Error:122
Any ideas?

Getting byte[] from GetClipboardData native method

I'm trying to get the Clipboard data using this native method with C#/.NET. The problem is I'm mangling the data. Here's my code:
IntPtr pointer = GetClipboardData(dataformat);
int size = Marshal.SizeOf(pointer);
byte[] buff = new byte[size];
Marshal.Copy(data, buff, 0, size);
Here's the pinvoke I'm using for the GetClipboardData method:
[DllImport("user32.dll")]
private static extern IntPtr GetClipboardData(uint uFormat);
Can anyone tell me where I'm going wrong?
If you want to get byte array from clipboard, which represents unicode text for example, the code will be something like this:
using System;
using System.Runtime.InteropServices;
using System.Text;
public class ClipboardHelper
{
#region Win32
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsClipboardFormatAvailable(uint format);
[DllImport("User32.dll", SetLastError = true)]
private static extern IntPtr GetClipboardData(uint uFormat);
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseClipboard();
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern int GlobalSize(IntPtr hMem);
private const uint CF_UNICODETEXT = 13U;
#endregion
public static string GetText()
{
if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
return null;
try
{
if (!OpenClipboard(IntPtr.Zero))
return null;
IntPtr handle = GetClipboardData(CF_UNICODETEXT);
if (handle == IntPtr.Zero)
return null;
IntPtr pointer = IntPtr.Zero;
try
{
pointer = GlobalLock(handle);
if (pointer == IntPtr.Zero)
return null;
int size = GlobalSize(handle);
byte[] buff = new byte[size];
Marshal.Copy(pointer, buff, 0, size);
return Encoding.Unicode.GetString(buff).TrimEnd('\0');
}
finally
{
if (pointer != IntPtr.Zero)
GlobalUnlock(handle);
}
}
finally
{
CloseClipboard();
}
}
}

exception calling CertFreeCertificateContext during callback using PInvoke to access ldap functionality

I am getting access violation exceptions when running the code below when the CertFreeCertificateContext method is invoked.
I imagine it is because of the way the pServerCert argument is being Mashalled on the LdapServerCertDelegate but have been unable to find a solution.
using System;
using System.Runtime.InteropServices;
namespace ldaptest
{
class Program
{
static void Main(string[] args)
{
new LdapAuthenticationProvider().AuthenticateUser("a.qas", "a", "administrator", "test123");
}
}
public class LdapAuthenticationProvider
{
public void AuthenticateUser(string server, string domain, string username, string password)
{
IntPtr ld = ldap_sslinit(server, LDAP_SSL_PORT, 1);
if (IntPtr.Zero == ld) throw new Exception("ldap_sslinit");
var version = new IntPtr(LDAP_VERSION3);
var ret = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, version);
if (ret != LDAP_SUCCESS) throw new Exception(string.Format("LDAP_OPT_PROTOCOL_VERSION 0x{0:X}", ret));
var ldapOn = new IntPtr(LDAP_OPT_ON);
ret = ldap_set_option(ld, LDAP_OPT_SSL, ldapOn);
if (ret != LDAP_SUCCESS) throw new Exception(string.Format("LDAP_OPT_SSL 0x{0:X}", ret));
// note the necessity to convert the delegate to a function pointer
var callback = new LdapServerCertDelegate(AcceptAnySslCertificate);
IntPtr pFn = Marshal.GetFunctionPointerForDelegate(callback);
ret = ldap_set_option(ld, LDAP_OPT_SERVER_CERTIFICATE, pFn);
if (ret != LDAP_SUCCESS) throw new Exception(string.Format("LDAP_OPT_SERVER_CERTIFICATE 0x{0:X}", ret));
var tv = new l_timeval();
ret = ldap_connect(ld, ref tv);
if (ret != LDAP_SUCCESS) throw new Exception(string.Format("ldap_connect 0x{0:X}", ret));
string login = string.Format(#"{0}\{1}", domain, username);
ret = ldap_bind_s(ld, login, password, LDAP_AUTH_SIMPLE); // triggers the callback
if (ret != LDAP_SUCCESS) throw new Exception(string.Format("ldap_bind_s 0x{0:X}", ret));
ldap_unbind_s(ld);
Console.WriteLine("Success");
Console.Read();
}
private delegate bool LdapServerCertDelegate(IntPtr connection, IntPtr pServerCert);
private bool AcceptAnySslCertificate(IntPtr connection, IntPtr pServerCert)
{
CertFreeCertificateContext(pServerCert); // << System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
return true;
}
#region crypt32.dll functions
[DllImport("crypt32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CertFreeCertificateContext(IntPtr pCertContext);
#endregion
#region Winldap.h definitions
private const int LDAP_PORT = 389;
private const uint LDAP_SSL_PORT = 636;
private const int LDAP_VERSION3 = 3;
private const int LDAP_OPT_PROTOCOL_VERSION = 17;
private const int LDAP_OPT_SSL = 10;
private const int LDAP_OPT_ON = 1;
private const int LDAP_AUTH_SIMPLE = 128;
private const int LDAP_OPT_SERVER_CERTIFICATE = 129;
private const uint LDAP_SUCCESS = 0;
[StructLayoutAttribute(LayoutKind.Sequential)]
private struct l_timeval
{
private int tv_sec;
private int tv_usec;
}
#endregion
#region wldap32.dll functions
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/ldap_sslinit.asp?frame=true
[DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_sslinitW",
SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr ldap_sslinit(string hostName, uint portNumber, int secure);
[DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW",
SetLastError = true, CharSet = CharSet.Unicode)]
private static extern uint ldap_set_option([In] IntPtr ldapHandle, int option, IntPtr invalue);
[DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_unbind_s",
SetLastError = true, CharSet = CharSet.Unicode)]
private static extern uint ldap_unbind_s([In] IntPtr ldapHandle);
[DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_connect",
SetLastError = true, CharSet = CharSet.Unicode)]
private static extern uint ldap_connect([In] IntPtr ld, [In] ref l_timeval timeout);
[DllImport("wldap32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_bind_sW",
SetLastError = true, CharSet = CharSet.Unicode)]
private static extern uint ldap_bind_s([In] IntPtr ld, string dn, string cred, uint method);
#endregion
}
}
best bet turned out to be avoiding PInvoke and using C++/CLI.

How do I set the credentials of a a windows service log on?

How do I programmatically set the "Log On" credentials for an arbitrary Windows service using c# (wmi/interop is fine)?
Note, my program is running as an administrator and I need the change to persist (for all subsequent service restarts)
Ideally the method has the following sig:
void SetWindowsServiceCreds(string serviceName, string username, string password)
{
// TODO write me
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ChangeServiceConfig(IntPtr hService, UInt32 nServiceType, UInt32 nStartType, UInt32 nErrorControl, String lpBinaryPathName, String lpLoadOrderGroup, IntPtr lpdwTagId, String lpDependencies, String lpServiceStartName, String lpPassword, String lpDisplayName);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr OpenSCManager(
string machineName,
string databaseName,
uint dwAccess);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseServiceHandle(IntPtr hSCObject);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryConfig, UInt32 cbBufSize, out UInt32 pcbBytesNeeded);
[StructLayout(LayoutKind.Sequential)]
public class QUERY_SERVICE_CONFIG
{
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwServiceType;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwStartType;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwErrorControl;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpBinaryPathName;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpLoadOrderGroup;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwTagID;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpDependencies;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpServiceStartName;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpDisplayName;
};
private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F;
private const uint SERVICE_QUERY_CONFIG = 0x00001;
private const uint SERVICE_CHANGE_CONFIG = 0x00002;
private const uint SERVICE_NO_CHANGE = 0xffffffff;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
public static void SetWindowsServiceCreds(string serviceName, string username, string password)
{
IntPtr hManager = IntPtr.Zero;
IntPtr hService = IntPtr.Zero;
try
{
hManager = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
if (hManager == IntPtr.Zero)
{
ThrowWin32Exception();
}
hService = OpenService(hManager, serviceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
if (hService == IntPtr.Zero)
{
ThrowWin32Exception();
}
if (!ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, username, password, null))
{
ThrowWin32Exception();
}
}
finally
{
if (hService != IntPtr.Zero) CloseServiceHandle(hService);
if (hManager != IntPtr.Zero) CloseServiceHandle(hManager);
}
}
private static void ThrowWin32Exception()
{
int error = Marshal.GetLastWin32Error();
Win32Exception e = new Win32Exception(error);
throw e;
}
This works as well:
void SetWindowsServiceCreds(string serviceName, string username, string password)
{
string objPath = string.Format("Win32_Service.Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
object[] wmiParams = new object[10];
wmiParams[6] = username;
wmiParams[7] = password;
service.InvokeMethod("Change", wmiParams);
}
}

Categories

Resources