wallpaper changing on windows 7 - c#

I have a problem with changing wallpaper via code, i have below code as every SO/Codeproject threads talks about on changing wallpaper. (Have not tested on other Win OS so far)
const int SPI_SETDESKWALLPAPER = 20;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDWININICHANGE = 0x02;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int SystemParametersInfo(
int uAction, int uParam, string lpvParam, int fuWinIni);
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, #"C:\Temp\100_5715.JPG.bmp",
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
The actual problem i have here is that if i make the above code as windows service and install it as a "Local Service" or "Local System", it wont work at all. But if i make the above code as a ConsoleApp, then things work.
I wonder whats the problem? Yes my user account has Admin rights. Also i have Windows 7 Ultimate here.
Thanks :)

Services run in their own session, called session 0 since Vista. It is isolated from the user session for security reasons, services run with a very privileged account. You are changing the desktop of that otherwise invisible session.
You can't use a service.

Related

Clear web browser cookies winforms C#

How I can clear cookies for web browser control winforms C# , is there any way to clear cookies problematically in winforms web browser control
You can disable cache (including cookies) before navigating to the site. To do so, you can use InternetSetOption API function and set the value of INTERNET_OPTION_SUPPRESS_BEHAVIOR(81) option to INTERNET_SUPPRESS_COOKIE_PERSIST(3) value.
Example
The following example, works like starting a new session. While I've logged in to the outlook.com on my machine, but when I open this application and browse outlook.com after disabling cookies and cache, it works like starting a new session and I need to login to outlook.com:
//using System.Runtime.InteropServices;
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption,
IntPtr lpBuffer, int dwBufferLength);
private void Form1_Load(object sender, EventArgs e)
{
var ptr = Marshal.AllocHGlobal(4);
Marshal.WriteInt32(ptr, 3);
InternetSetOption(IntPtr.Zero, 81, ptr, 4);
Marshal.Release(ptr);
webBrowser1.Navigate("https://outlook.com");
}
To find more information about these flags, take a look at Windows Internet Option Flags.
Note: You can find a VB.NET version of this answer, here in my other post.

Get HDD serial over shared path

I have a C# win form app. In it I'm getting a unique serial of HDD by using this method.
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool GetVolumeInformation(string Volume, StringBuilder VolumeName,
uint VolumeNameSize, out uint SerialNumber, uint SerialNumberLength,
uint flags, StringBuilder fs, uint fs_size);
with Volume variable as Path.GetPathRoot(Environment.CurrentDirectory)
I get the serial as SerialNumber.ToString("X")
Works fine but the situation is;
I have Shared the app folder. I get XXXXXXXX as serial when I run the EXE
When another person run the app from my shared path he gets 00000000 as serial
But when that another user Mapped this folder and run the app he gets XXXXXXXX as serial
So what is the cause of this problem? Is there any better way to use?
I referred WMI but didn't fit to my need.

control the Windows Service

We need to control the Windows Service remotely using the .net application. Example: we have 10 windows services on different services. Now I want to create the application(I guess it is also a windows service) to start and stop these service remotely, and also install or uninstall them via command line.
First thing is to collect these services name. Then using a loop or if/else I guess. Before that I want to make sure all services are installed. I don't want to access service manager to install services, I want to implement it in the code.
I got a hint from somewhere but still not sure exactly.
ServiceInstaller.InstallService("\"" + _applicationPath + "\\" + _applicationName + ".exe\" -service", _applicationName, _applicationName, autoInstall, autoRun);
internal static bool InstallService(string svcPath, string svcName, string svcDispName, bool autoStart, bool startNow)
{
#region Constants declaration.
int SC_MANAGER_CREATE_SERVICE = 0x0002;
int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
int SERVICE_DEMAND_START = 0x00000003;
int SERVICE_ERROR_NORMAL = 0x00000001;
int STANDARD_RIGHTS_REQUIRED = 0xF0000;
int SERVICE_QUERY_CONFIG = 0x0001;
int SERVICE_CHANGE_CONFIG = 0x0002;
int SERVICE_QUERY_STATUS = 0x0004;
int SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
int SERVICE_START = 0x0010;
int SERVICE_STOP = 0x0020;
int SERVICE_PAUSE_CONTINUE = 0x0040;
int SERVICE_INTERROGATE = 0x0080;
int SERVICE_USER_DEFINED_CONTROL = 0x0100;
int SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SERVICE_QUERY_CONFIG |
SERVICE_CHANGE_CONFIG |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS |
SERVICE_START |
SERVICE_STOP |
SERVICE_PAUSE_CONTINUE |
SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL);
int SERVICE_AUTO_START = 0x00000002;
#endregion Constants declaration.
try
{
int dwStartType = SERVICE_AUTO_START;
if (autoStart == false) dwStartType = SERVICE_DEMAND_START;
IntPtr sc_handle = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);
if (sc_handle.ToInt32() != 0)
{
IntPtr sv_handle = CreateService(sc_handle, svcName, svcDispName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, dwStartType, SERVICE_ERROR_NORMAL, svcPath, null, 0, null, null, null);
if (sv_handle.ToInt32() == 0)
{
CloseServiceHandle(sc_handle);
return false;
}
else
My questions:
1) How to collect services?
2) How to start/stop the services?
3) Install service code, no clue.
You can use the ServiceController class to remotely control services on another computer provided that your application is running with the necessary rights and nothing like a firewall is blocking the connection.
Get all services on a remote computer:
var services = ServiceController.GetServices(machineName);
To start and stop a specific service on a remote computer you can use LINQ to get a specific service from the list retrieved above:
var services = ServiceController.GetServices(machineName);
var service = services.First(s => s.ServiceName == "MyServiceName");
service.Start();
...
service.Stop();
Another option is to get a specific service on a specific machine:
var service = new ServiceController("MyServiceName", machineName);
To install a new service you have multiple options. If you are writing your own services in .NET you can create an MSI package using WiX. You can also use the ServiceInstaller class with or without InstallUtil.exe or you can install any service even remotely using SC.exe.
However, to install a service remotely you still should place the executable file of the service locally on the remote computer. So installing a service remotely really involves getting the service onto the remote computer and then run some process to perform the actual installation which will create the correct entries in the registry database. You will have to decide if you want to use file shares, WMI, remote PowerShell or perhaps Active Directory to distribute the software.
Maybe using net command from the shell is a way to go? It is able to list, start, stop services etc. You'll feel a little 'dirty' if you use it, but heck, it will work.
How do I restart a service on a remote machine in Windows?
An yes, I would recommend wrapping that under simple WEB service app.
Also to read: Simplest way to restart service on a remote computer
What about ServiceController class?
http://msdn.microsoft.com/library/system.serviceprocess.servicecontroller.aspx
If service isn't installed ServiceController.Status will throw InvalidOperationException
ServiceController.GetServices() will get you a list of services. It can work on remote computers too, but the code must have correct permissions (impersonation, maybe?)
There is also this: http://www.codeproject.com/Articles/4242/Command-Line-Windows-Services-Manager
In Windows InstallUtil.exe can be used to install/uninstall services. But you must use the correct version: there can be more than one, depending on .NET version and system (x64, x32). On your own machine (I don't know about remote machines) the correct path is:
string path = Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "InstallUtil.exe");
You can execute a process on another machine using PsExec or WMI
EDIT:
.bat script to install a service on your own machine (x64 version of installutil installs x64 version of service):
#ECHO OFF
REM The following directory is for .NET 2.0
set DOTNETFX2=%SystemRoot%\Microsoft.NET\Framework64\v2.0.50727
set PATH=%PATH%;%DOTNETFX2%
echo Installing WindowsService...
echo ---------------------------------------------------
InstallUtil /i "service path goes here"
echo ---------------------------------------------------
echo Done.

Cannot communicate successfully with USB HID device using writefile()

I am fairly new to C# as well as windows programming and I am attempting to establish communication between a USB HID device and an app written in c# on a windows xp pc. I have obtained the device path successfully and have used this to establish a valid Handle on the device:
IntPtr drive = CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero,
OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, IntPtr.Zero);
This proved to be a valid handle that yields a positive integer when tested. After creating the handle I call 'HidD_GetPreparsedData' and 'HidP_GetCaps' which yield a struct previously imported (HIDP_CAPS) that stores specific data related to the device attached. Next, I try to call writefile():
bool success = WriteFile(drive, ref outputReportBuffer,
caps.OutputReportByteLength, ref numberOfBytesWritten,
IntPtr.Zero);
drive: The Handle of the device
outputReportBuffer:The array of bytes to write [65]
caps.OutputReportByteLength: The amount of bytes to write, caps is the struct of HIDP_CAPS
numberOfBytesWritten: hardcoded to 0
IntPtr.Zero: Everything I have read passes this last parameter as I have done. In the formal parameters of 'writefile' the last parameter is listed as 'IntPtr ipOverlapped', but I have not been able to figure out what that is, except that It should be passed as some form of 0
How WriteFile is imported:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteFile(IntPtr hFile,
ref byte[] lpBuffer,
uint nNumberOfBytesToWrite,
ref uint lpNumberOfBytesWritten,
IntPtr ipOverlapped);
When writefile is executed it simply does nothing. I get no error, but when tested, it reveals that communication was never established and it was not successful. If anyone could share any knowledge or provide any resources to help I would really appreciate it. Thank you for reading.
Regards.
Remove the ref in your WriteFile declaration.
While http://www.pinvoke.net/ is a great resource for P/Invoke declarations, it's a wiki-style website and many declarations are wrong (often they won't work on a x64 machine).

User32 API custom PostMessage for automatisation

I want to automate a program called Spotify from C#, the best way (I think) to do this is by triggering fake keypresses. I want to program to pause playback, and I don't know enough about this stuff to find another way than keypresses. So I use Visual Studio's Spy++ to see what message Spotify gets when pressing the play button on my keyboard, I copy the data from that message into my Console Application and run it, when I run I can see the PostMessage in Spy++'s Message Logging, so this is working but it doesn't pause/play my music. I guess this is because I also have to send another PostMessage with another destination, but how do I know what else to send?
Post Message call:
MessageHelper.PostMessage((int)hwndSpotify, 0x100, 0x000000B3, 0x01000001);
I hope someone is familiar with this and can help me out.
To automate Spotify, first you have to get the handle of the window with the following class name: SpotifyMainWindow (using FindWindow()).
Then, you can use the SendMessage() method to send a WM_APPCOMMAND message to the Spotify's window.
Following a simple code to do that:
internal class Win32
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
internal class Constants
{
internal const uint WM_APPCOMMAND = 0x0319;
}
}
public enum SpotifyAction : long
{
PlayPause = 917504,
Mute = 524288,
VolumeDown = 589824,
VolumeUp = 655360,
Stop = 851968,
PreviousTrack = 786432,
NextTrack = 720896
}
For instance, to play or pause the current track:
Win32.SendMessage(hwndSpotify, Win32.Constants.WM_APPCOMMAND, IntPtr.Zero, new IntPtr((long)SpotifyAction.PlayPause));
Pressing the "play buttion" results in a virtual key code - for an official list see http://msdn.microsoft.com/en-us/library/dd375731%28v=VS.85%29.aspx .
There you find for example VK_VOLUME_UP VK_MEDIA_PLAY_PAUSE VK_ZOOM .
Even some Remotes translate to these codes to be as compatible as possible with existing software.
These were introduced back in the day when Windows ME (!) came out and are still in use - at least when I checked the registry of my Windows 2008 R2 !
Basically Windows translates certain VK* into WM_APPCOMMAND messages with certain codes which the applications listen to...
If the key has something to do with launching an app to do (i.e. Mail, Browser etc.) then the magic happens via Windows Explorer which reads the mapping (either by association or direct exec) from the registry at Software\ Microsoft\ Windows\ CurrentVersion\ Explorer\ AppKey - either HKLM or HKCU.
Some links with old but as it seems still valid information:
http://msdn.microsoft.com/en-us/windows/hardware/gg463446.aspx
http://msdn.microsoft.com/en-us/windows/hardware/gg462991
http://msdn.microsoft.com/en-us/windows/hardware/gg463372

Categories