The following problem is driving me crazy. In C#, I am trying to ensure that outlook shuts down after I run some code to grab all calendar events, yet no matter what I try, it doesn't. Can anyone help me?
private void button1_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Outlook.Application outlookApp = null;
Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = null;
Microsoft.Office.Interop.Outlook.MAPIFolder CalendarFolder = null;
Microsoft.Office.Interop.Outlook.Items outlookCalendarItems = null;
outlookApp = new Microsoft.Office.Interop.Outlook.Application();
mapiNamespace = outlookApp.GetNamespace("MAPI");
CalendarFolder = mapiNamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);
outlookCalendarItems = CalendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = true;
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in outlookCalendarItems)
{
if (item.IsRecurring)
{
Microsoft.Office.Interop.Outlook.RecurrencePattern rp = item.GetRecurrencePattern();
DateTime first = new DateTime(2008, 8, 31, item.Start.Hour, item.Start.Minute, 0);
DateTime last = new DateTime(2008, 10, 1);
Microsoft.Office.Interop.Outlook.AppointmentItem recur = null;
for (DateTime cur = first; cur <= last; cur = cur.AddDays(1))
{
try
{
recur = rp.GetOccurrence(cur);
MessageBox.Show(recur.Subject + " -> " + cur.ToLongDateString());
}
catch
{
}
}
}
else
{
MessageBox.Show(item.Subject + " -> " + item.Start.ToLongDateString());
break;
}
}
((Microsoft.Office.Interop.Outlook._Application)outlookApp).Quit();
//outlookApp.Quit();
//(outlookApp as Microsoft.Office.Interop.Outlook._Application).Quit();
outlookApp = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(outlookCalendarItems);
System.Runtime.InteropServices.Marshal.ReleaseComObject(CalendarFolder);
System.Runtime.InteropServices.Marshal.ReleaseComObject(mapiNamespace);
//System.Runtime.InteropServices.Marshal.ReleaseComObject(outlookApp);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(outlookCalendarItems);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(CalendarFolder);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(mapiNamespace);
//System.Runtime.InteropServices.Marshal.FinalReleaseComObject(outlookApp);
GC.Collect();
GC.WaitForPendingFinalizers();
mapiNamespace = null;
CalendarFolder = null;
outlookCalendarItems = null;
}
Temporary hardcore solution:
public static class OutlookKiller
{
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
private static extern long GetWindowThreadProcessId(long hWnd, out long lpdwProcessId);
public static void Kill(ref Microsoft.Office.Interop.Outlook.Application app)
{
long processId = 0;
long appHwnd = (long)app.Hwnd;
GetWindowThreadProcessId(appHwnd, out processId);
Process prc = Process.GetProcessById((int)processId);
prc.Kill();
}
}
Have you debugged your code to see if the application ever gets to the OutlookApp.Quit() command?
The only other way around this would be to crudley kill the process "Outlook.exe".
This should work for any and App by referencing the App Name and it will kill all instances of the application.
For instance if you have 5 instances of Notepad, it will kill them all...
using System.Management;
using System.Diagnostics;
public static class KillProcessByPID
{
public static void KillProcessByName(string ProcessName)
{
string OutlookProcessName = "";
foreach (Process otlk in Process.GetProcesses())
{
if (otlk.ProcessName.ToLower().Contains(ProcessName.ToLower())) //OUTLOOK is the one I am seeking - yours may vary
{
OutlookProcessName = otlk.ProcessName;
}
}
//Get process ID by Name
var processes = Process.GetProcessesByName(OutlookProcessName);
foreach (var process in processes)
{
Console.WriteLine("PID={0}", process.Id);
Console.WriteLine("Process Handle={0}", process.Handle);
KillProcessAndChildren(process.Id);
}
}
/// <summary>
/// Kill a process, and all of its children, grandchildren, etc.
/// </summary>
/// <param name="pid">Process ID.</param>
public static void KillProcessAndChildren(int pid)
{
//Process[] remoteByName = Process.GetProcessesByName("notepad", "myComputer");
// Cannot close 'system idle process'.
if (pid == 0)
{
return;
}
ManagementObjectSearcher searcher = new ManagementObjectSearcher
("Select * From Win32_Process Where ParentProcessID=" + pid);
ManagementObjectCollection moc = searcher.Get();
foreach (ManagementObject mo in moc)
{
KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
}
try
{
Process proc = Process.GetProcessById(pid);
proc.Kill();
}
catch (ArgumentException)
{
// Process already exited.
}
}
}
I call it at the beginning and end of my app with the following one Killer line of code:
KillProcessByPID.KillProcessByName("OUTLOOK");
I borrowed from many and I'm not sure where, but I thank you all and give you all credit... apologies for not referencing you directly, but this was instrumental.
Related
I'm using the following code to kill a remote desktop session and the application running in it. It works fine, the only problem is that it kills the specified application for all users.
How do I keep this to just the local machine running a session?
We have multiple users logging in and running this application from a server on their local machines. Most are running using work resources, but some use remote desktop.
No matter how they are logged in when I run my code all users loose their sessions.
private void btnCloseSession_Click(object sender, EventArgs e)
{
if (!runningExclusiveProcess)
{
runningExclusiveProcess = true;
btnCloseSession.Enabled = false;
//check and close Labware if running
if (chkCloseLabware.Checked == true)
{
if (chkExit.Checked == true)
{
KillLabWare();
Close();
}
else
{
KillLabWare();
}
}
Process[] my = Process.GetProcessesByName("mstsc");
//loop thru list to get selected item(s)
ListBox.SelectedObjectCollection selectedItems = new ListBox.SelectedObjectCollection(lstOpenSessions);
selectedItems = lstOpenSessions.SelectedItems;
try
{
//remove credentials
string szTestx = "/delete:GOJO.NET/" + cboServer.Text;
ProcessStartInfo infox = new ProcessStartInfo("cmdkey.exe", szTestx);
Process procx = new Process();
procx.StartInfo = infox;
procx.Start();
if (lstOpenSessions.SelectedIndex != -1)
{
for (int i = selectedItems.Count - 1; i >= 0; i--)
{
//loop thru process to match process vs. list selection(s)
foreach (Process remote in my)
{
if (remote.MainWindowTitle == selectedItems[i].ToString())
{
KillRS(remote.MainWindowTitle);
lstOpenSessions.Items.Remove(selectedItems[i]);
}
}
if (lstOpenSessions.Items.Contains(selectedItems[i].ToString()))
{
lstOpenSessions.Items.Remove(selectedItems[i]);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("{0} Exception caught.", ex);
}
// If your task is synchronous, then undo your flag here:
runningExclusiveProcess = false;
btnCloseSession.Enabled = true;
}
}
public void KillLabWare()
{
ConnectionOptions con = new ConnectionOptions();
con.Username = cboUserName.Text;
con.Password = txtPassWord.Text;
string strIPAddress = cboServer.Text;
ManagementScope scope = new
ManagementScope(#"\\" + strIPAddress + #"\root\cimv2", con);
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Process WHERE Name='Labware.exe'");
ManagementObjectSearcher searcher = new
ManagementObjectSearcher(scope, query);
ManagementObjectCollection objectCollection = searcher.Get();
foreach (ManagementObject managementObject in objectCollection)
{
managementObject.InvokeMethod("Terminate", null);
}
}
private void KillRS(string rwt)
{
foreach (Process p in Process.GetProcesses())
{
if (p.MainWindowTitle == rwt)
{
p.Kill();
}
}
}
public static void KillRemoteProcess(Process p, string user, string password)
{
new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "TaskKill.exe",
Arguments = string.Format("/pid {0} /s {1} /u {2} /p {3}", p.Id, p.MachineName, user, password),
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true
}
}.Start();
}
It sounds like you are trying to force a specific user to log out? Is this because you find that users are forgetting to log out and constantly consuming licenses?
LabWare Application allows for a time out interval (in minutes) to be set on each user where after the interval has passed, the user will be logged out (licence no longer consumed).
For more information see page 204 of the LabWare 7 Technical Manual.
Alternativley if this is for a scheduler (service or cluster instance) session, this can also be controlled by the application. You can either manually change the shutdown and keep alive flags on the instance record on the Services table (if using Service Manager) or you can write a LIMS Basic event trigger/automation script or scheduled subroutine (or have this as a button on a Visual workflow) to do this for you.
HTH.
If you wanna kill remote desktop session or disconnect current RDP session, please read this article:
WTSDisconnectSession function
but if you logout current user, it also disconnect RDP session, here is the code:
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
class Program
{
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSDisconnectSession(IntPtr hServer, int sessionId, bool bWait);
const int WTS_CURRENT_SESSION = -1;
static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
static void Main(string[] args)
{
if (!WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,
WTS_CURRENT_SESSION, false))
throw new Win32Exception();
}
}
I hope it works, fill free for further info, comment plz
Happy Coding 😎
I have made an application to log all websites visited by current PC user. This is not for a malicious use. I am making this feature for my employee monitoring software which will be licensed under proper laws.
Coming on main point, Whenever I am fetching URL from any browser such as IE. I am only getting its URL for all opened tabs. I am unable to get any tab handle for IE7+ , because of which I am unable to maintain a list of tabs for which I have already logged URL's for same tab.
Below is my code (Take a Look on Commented Code First):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WebsiteLoggerConsole
{
public class WebLogger
{
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindow);
System.Threading.Timer log;
public void StartLoggin()
{
try
{
TimerCallback logcallback = new TimerCallback(LogTick);
log = new System.Threading.Timer(logcallback, null, 0, 2000);
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
}
}
public void StopLogging()
{
try
{
log.Dispose();
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
}
}
public void LogTick(Object stateInfo)
{
CreateLog();
}
void CreateLog()
{
try
{
SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();
string filename;
foreach (SHDocVw.InternetExplorer ie in shellWindows)
{
filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
if (filename.Equals("iexplore"))
{
int val = ie.HWND;
IntPtr hwnd = new IntPtr(val);
IntPtr uihwnd = GetDirectUIHWND(hwnd);
string ddd = (ie.LocationURL) + " :::: " + (uihwnd.ToString());
Console.WriteLine(ddd);
}
}
//SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();
//string filename;
//foreach (SHDocVw.InternetExplorer ie in shellWindows)
//{
// filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
// if (filename.Equals("iexplore"))
// {
// int val = ie.HWND;
// IntPtr hwnd = new IntPtr(val);
// IntPtr uihwnd = GetDirectUIHWND(hwnd);
// IntPtr tabhwnd = GetDirectUIHWND(uihwnd);
// string ddd = (ie.LocationURL) + " :::: " + (tabhwnd.ToString());
// Console.WriteLine(ddd);
// }
//}
//Process[] processlist = Process.GetProcesses();
//foreach (Process theprocess in processlist)
//{
// if (theprocess.ProcessName == "iexplore")
// {
// Console.WriteLine("Process: {0}, ID: {1}, Handle: {3}, Window name: {2}",
// theprocess.ProcessName, theprocess.Id, theprocess.MainWindowTitle, theprocess.SessionId.ToString()
// );
// }
//}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
}
}
private static IntPtr GetDirectUIHWND(IntPtr ieFrame)
{
// try IE 9 first:
IntPtr intptr = FindWindowEx(ieFrame, IntPtr.Zero, "WorkerW", null);
if (intptr == IntPtr.Zero)
{
// IE8 and IE7
intptr = FindWindowEx(ieFrame, IntPtr.Zero, "CommandBarClass", null);
}
intptr = FindWindowEx(intptr, IntPtr.Zero, "ReBarWindow32", null);
//intptr = FindWindowEx(intptr, IntPtr.Zero, "TabBandClass", null);
//intptr = FindWindowEx(intptr, IntPtr.Zero, "DirectUIHWND", null);
return intptr;
}
}
}
I provided a solution on this topic: How to write a standalone URL logger for Windows?
There I used Java, but you can do the same by using C#. I am almost sure there is a lot of good libpcap wrappers for C#.
There is a project called pcapDotNet and you can use it.
Adjusting one example:
using System;
using System.Collections.Generic;
using PcapDotNet.Core;
using PcapDotNet.Packets;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport;
namespace InterpretingThePackets
{
class Program
{
static void Main(string[] args)
{
// Retrieve the device list from the local machine
IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;
if (allDevices.Count == 0)
{
Console.WriteLine("No interfaces found! Make sure WinPcap is installed.");
return;
}
// Print the list
for (int i = 0; i != allDevices.Count; ++i)
{
LivePacketDevice device = allDevices[i];
Console.Write((i + 1) + ". " + device.Name);
if (device.Description != null)
Console.WriteLine(" (" + device.Description + ")");
else
Console.WriteLine(" (No description available)");
}
int deviceIndex = 0;
do
{
Console.WriteLine("Enter the interface number (1-" + allDevices.Count + "):");
string deviceIndexString = Console.ReadLine();
if (!int.TryParse(deviceIndexString, out deviceIndex) ||
deviceIndex < 1 || deviceIndex > allDevices.Count)
{
deviceIndex = 0;
}
} while (deviceIndex == 0);
// Take the selected adapter
PacketDevice selectedDevice = allDevices[deviceIndex - 1];
// Open the device
using (PacketCommunicator communicator =
selectedDevice.Open(65536, // portion of the packet to capture
// 65536 guarantees that the whole packet will be captured on all the link layers
PacketDeviceOpenAttributes.Promiscuous, // promiscuous mode
1000)) // read timeout
{
// Check the link layer. We support only Ethernet for simplicity.
if (communicator.DataLink.Kind != DataLinkKind.Ethernet)
{
Console.WriteLine("This program works only on Ethernet networks.");
return;
}
// Compile the filter
using (BerkeleyPacketFilter filter = communicator.CreateFilter("ip and tcp"))
{
// Set the filter
communicator.SetFilter(filter);
}
Console.WriteLine("Listening on " + selectedDevice.Description + "...");
// start the capture
communicator.ReceivePackets(0, PacketHandler);
}
}
// Callback function invoked by libpcap for every incoming packet
private static void PacketHandler(Packet packet)
{
// print timestamp and length of the packet
Console.WriteLine(packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") + " length:" + packet.Length);
IpV4Datagram ip = packet.Ethernet.IpV4;
//Do your magic here using HttpRequestDatagram
}
}
}
I wrote a C# app which takes screenshot every 5 mins a saves it to server. It is timer, 2 threads, few methods(ping srv, check folder, take screenshot etc.).
As process (exe) it runs great, but I need to install it as service. I am installing it trough installutil (Framework service installer).
My problem is, that when it is installed as service, it doesn't take screenshots. Pull out some, when stopping the service. Not the right resolution and black.
I assume, that the executive code is misplaced (see main). I don't know where to put it, since I cannot have more than one main method. Please help.
Code of main application:
I've deleted some not important code.
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
//using System.Timers;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.ComponentModel;
using System.Configuration.Install;
namespace LogWriterService
{
static class Program
{
public static int TimeO = 5; // zpoždění časovače v minutách
private static bool Online;
private static bool active = false;
public static String GetIP()
{
// ...
// returns IP like xxx.xxx.xxx.xxx
// ...
}
// Test dostupnosti serveru
public static bool PingTest()
{
// ...
// return true if server is reachable
// ...
}
/*
* Z Windows.Forms _ screenů získá obrazová data, která uloží na
* server jako ../[IP]/[současný_systémový_čas].jpg
*/
public static void ScreenShot() //Bitmap
{
Int64 CurrTime = Int64.Parse(DateTime.Now.ToString("yyyyMMddhhmmss")); //yyyyMMddhhmmss
Rectangle bounds = Rectangle.Empty;
foreach (Screen s in Screen.AllScreens)
bounds = Rectangle.Union(bounds, s.Bounds);
Bitmap screenShotBMP = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); // PixelFormat.Format32bppArgb
Graphics screenShotGraphics = Graphics.FromImage(screenShotBMP);
screenShotGraphics.CopyFromScreen(bounds.X, bounds.Y,
0, 0, bounds.Size, CopyPixelOperation.SourceCopy);
string path = null; //"D:/TEMP/" + CurrTime + ".jpg"; // GetIP()
// Ukládání obrázků do dočasné složky a přesun, pokud se připojí
if (PingTest() == true)
{
path = "//10.0.0.10/Upload/screen/test/" + GetIP() + "/" + CurrTime + ".jpg";
string path2 = "//10.0.0.10/Upload/screen/test/" + GetIP() + "/";
Online = true;
if (Directory.Exists(path2))
{
MoveCached();
}
else
{
Console.WriteLine("Online slozka neni dostupna.");
}
} else {
Console.WriteLine("Caching .. ");
path = "C:/TEMP/" + CurrTime + ".jpg"; // "C:/TEMP/" + GetIP() + "/" + CurrTime + ".jpg"
string LPath = #"c:\TEMP";
if (!Directory.Exists(LPath))
{
DirectoryInfo di = Directory.CreateDirectory(LPath);
di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
Console.WriteLine("Lokalni slozka neexistuje. Vytvarim ..");
}
Online = false;
}
screenShotBMP.Save(path, ImageFormat.Jpeg); // C:\\test\\test.jpg
screenShotGraphics.Dispose();
screenShotBMP.Dispose();
return; //screenShotBMP;
}
/*
* Přesune cache soubory (za dobu offline) na server
*/
public static void MoveCached()
{
// ...
// after conect, move localy saved screenshots to server
// ...
}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
// Vytvoří událost signalizující hranici odpočtu ve
// zpětném volání časovače
AutoResetEvent autoEvent = new AutoResetEvent(false);
// Počet průchodů timeru
StatusChecker statusChecker = new StatusChecker(Timeout.Infinite); // 1440
// Vytvoří odvozeného delegáta, který vyvolá metody pro časovač
TimerCallback tcb = statusChecker.CheckStatus;
// Create a timer that signals the delegate to invoke
// CheckStatus after one second, and every 1/4 second
// thereafter.
System.Threading.Timer stateTimer = new System.Threading.Timer(tcb, autoEvent, 1000, TimeO * 1000); // TimeO * 1000 * 60 * 12 * 5, 250
// When autoEvent signals, change the period to every
// 1/2 second.
autoEvent.WaitOne(15000, false);
stateTimer.Change(0, TimeO * 1000 * 60); // TimeO * 1000 * 60
Console.WriteLine("menim poprve..");
// When autoEvent signals the second time, dispose of
// the timer.
autoEvent.WaitOne(Timeout.Infinite, false);
stateTimer.Change(0, TimeO * 1000 * 60); // TimeO * 1000 * 60
Console.WriteLine("menim podruhe..");
//stateTimer.Dispose();
// Garbage collector
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
class StatusChecker
{
private int invokeCount;
private int maxCount;
Int64 CurrTime = Int64.Parse(DateTime.Now.ToString("hh")); // screeny od 6:00 do 16:00
public StatusChecker(int count)
{
invokeCount = 0;
maxCount = count;
}
// Tato metoda je volána delegátem časovače
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
//if ((CurrTime > 6) & (CurrTime < 16)) // 16
//{
LogWriterService.Program.ScreenShot();
Console.WriteLine("ScreenShot ..");
//}
Console.WriteLine("{0} Kontroluji stav {1,2}.",
DateTime.Now.ToString("h:mm:ss.fff"),
(++invokeCount).ToString());
if (invokeCount == maxCount)
{
// Resetuje čítač a signál Main.
invokeCount = 0;
autoEvent.Set();
}
// Garbage collector
GC.Collect();
Console.WriteLine("Paměť uvolněna .. \n");
}
}
Code of service:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
namespace LogWriterService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
EventLog.WriteEntry("Sluzba screenshot se spustila.");
}
protected override void OnStop()
{
EventLog.WriteEntry("Sluzba screenshot se zastavila.");
}
}
}
I thing the problem may be here:
public static void CreateProcessAsUser()
{
IntPtr hToken = WindowsIdentity.GetCurrent().Token;
IntPtr hDupedToken = IntPtr.Zero;
ProcessUtility.PROCESS_INFORMATION pi = new ProcessUtility.PROCESS_INFORMATION();
try
{
ProcessUtility.SECURITY_ATTRIBUTES sa = new ProcessUtility.SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
bool result = ProcessUtility.DuplicateTokenEx(
hToken,
ProcessUtility.GENERIC_ALL_ACCESS,
ref sa,
(int)ProcessUtility.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)ProcessUtility.TOKEN_TYPE.TokenPrimary,
ref hDupedToken
);
if (!result)
{
throw new ApplicationException("DuplicateTokenEx failed");
}
ProcessUtility.STARTUPINFO si = new ProcessUtility.STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = String.Empty;
string folder = "D:\\test"; //Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string path = folder + "\\LogWriter\\LogWriter.exe"; // "C:/TEMP/" + GetIP() + "/" + CurrTime + ".jpg"
result = ProcessUtility.CreateProcessAsUser(
hDupedToken,
#path, // C:\Users\ToXiC\AppData\Roaming\LogWriter\LogWriter.exe
String.Empty,
ref sa, ref sa,
false, 0, IntPtr.Zero,
#"D:\\test", ref si, ref pi
);
if (!result)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
throw new ApplicationException(message);
}
}
finally
{
if (pi.hProcess != IntPtr.Zero)
ProcessUtility.CloseHandle(pi.hProcess);
if (pi.hThread != IntPtr.Zero)
ProcessUtility.CloseHandle(pi.hThread);
if (hDupedToken != IntPtr.Zero)
ProcessUtility.CloseHandle(hDupedToken);
}
}
}
The screenshots are all black I think. This happens because a windows service runs in Session 0 Isolation
One solution is to start a console application (with UI hidden) from the service after every 5 mins. The console application can take the screenshot and exit.
Some code to start a console app from windows service:
string applicationPath = ...;
private ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(applicationPath);
//set working directiory
Directory.SetCurrentDirectory(Path.GetDirectoryName(applicationPath));
psi.WorkingDirectory = Path.GetDirectoryName(applicationPath);
//psi.CreateNoWindow = false;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
//psi.UseShellExecute = false;
prcs = System.Diagnostics.Process.Start(psi);
Edit: The console application will be started in session 0. Workaround is to use the WIN API CreateProcessAsUser pinvoke call and start the console application in a user session.
Some links with code samples on how to achieve this:
http://odetocode.com/blogs/scott/archive/2004/10/28/createprocessasuser.aspx
http://blogs.msdn.com/b/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx
http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/31bfa13d-982b-4b1a-bff3-2761ade5214f/
Problem was with token. I found working solution here
how-can-windows-service-execute-gui
Thank you all for helping me out of it. I understand now much more how windows service works.
Why Register a DLL?
I have a lot of basic doubts on DLLs and i have tried to put them in a listed Questions form as below:
Why do we need to register a DLL?
What happens when we register a DLL?
When i use a "LoadLibrary" in my C# code, i do not do any registration.
Whats the connection/difference between the two?
(Registering a DLL and Loading a DLL)
Can i register all the DLLs? or are there some DLLs which cannot be registered and why?
If anyone can recommend some online articles for clarifying my doubts it would be big help!
otherwise snippet code.
im using this code but it doesnt give exactly what i need, thats why i asked here....
its working fine in 32-bit machine but it gives denied path error in 64 bit machine
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Security;
using System.Management;
using System.IO;
using CCC_DLLRegistar.LoadLibrary;
using System.Security.Principal;
using System.Diagnostics;
namespace CCC_DLLRegistar
{
public partial class Form1 : Form
{
#region Is64BitOperatingSystem (IsWow64Process)
public static bool Is64BitOperatingSystem()
{
if (IntPtr.Size == 8) // 64-bit programs run only on Win64
{
return true;
}
else // 32-bit programs run on both 32-bit and 64-bit Windows
{
// Detect whether the current process is a 32-bit process
// running on a 64-bit system.
bool flag;
return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") &&
IsWow64Process(GetCurrentProcess(), out flag)) && flag);
}
}
static bool DoesWin32MethodExist(string moduleName, string methodName)
{
IntPtr moduleHandle = GetModuleHandle(moduleName);
if (moduleHandle == IntPtr.Zero)
{
return false;
}
return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero);
}
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule,
[MarshalAs(UnmanagedType.LPStr)]string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
#endregion
#region Is64BitOperatingSystem (WMI)
public static bool Is64BitOperatingSystem(string machineName,
string domain, string userName, string password)
{
ConnectionOptions options = null;
if (!string.IsNullOrEmpty(userName))
{
options = new ConnectionOptions();
options.Username = userName;
options.Password = password;
options.Authority = "NTLMDOMAIN:" + domain;
}
// Else the connection will use the currently logged-on user
// Make a connection to the target computer.
ManagementScope scope = new ManagementScope("\\\\" +
(string.IsNullOrEmpty(machineName) ? "." : machineName) +
"\\root\\cimv2", options);
scope.Connect();
ObjectQuery query = new ObjectQuery(
"SELECT AddressWidth FROM Win32_Processor");
// Perform the query and get the result.
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject queryObj in queryCollection)
{
if (queryObj["AddressWidth"].ToString() == "64")
{
return true;
}
}
return false;
}
#endregion
public Form1()
{
InitializeComponent();
}
private string _RootPath = string.Empty;
private string _path = string.Empty;
private List<string> _Regfiles;
DLLHelper obj;
public string path
{
get { return _path; }
set { _path = value; }
}
public string RootPath
{
get { return _RootPath; }
set { _RootPath = value; }
}
private void Form1_Load(object sender, EventArgs e)
{
// Solution 1. Is64BitOperatingSystem (IsWow64Process)
// Determine whether the current operating system is a 64 bit
// operating system.
bool f64bitOS = Is64BitOperatingSystem();
//Console.WriteLine("The current operating system {0} 64-bit.",
// f64bitOS ? "is" : "is not");
// Solution 2. Is64BitOperatingSystem (WMI)
// Determine whether the current operating system is a 64 bit
// operating system through WMI. The function is also able to
// query the bitness of OS on a remote machine.
try
{
f64bitOS = Is64BitOperatingSystem(".", null, null, null);
//Console.WriteLine("The current operating system {0} 64-bit.",
// f64bitOS ? "is" : "is not");
if (f64bitOS == true)
{
RootPath = "C:\\windows\\SysWow64\\";
}
else
{
RootPath = "C:\\Windows\\System32\\";
}
bool isAdmin = new WindowsPrincipal(WindowsIdentity.GetCurrent())
.IsInRole(WindowsBuiltInRole.Administrator) ? true : false;
if (isAdmin)
{
MessageBox.Show("you are an administrator");
}
else
{
MessageBox.Show("You are not an administrator");
}
path = Application.StartupPath + "\\CCC DLL\\";
List<string> regsvr = new List<string>();
foreach (string s in Directory.GetFiles(path, "*.*").Select(Path.GetFileName))
{
regsvr.Add(Application.StartupPath + "\\CCC DLL\\" + s);
}
foreach (string filepath in regsvr)
{
Registar_Dlls(filepath);
}
_Regfiles=new List<string>();
foreach (string s in Directory.GetFiles(path, "*.dll").Select(Path.GetFileName))
{
_Regfiles.Add(Application.StartupPath + "\\CCC DLL\\" + s);
if (DLLHelper.UnmanagedDllIs64Bit(Application.StartupPath + "\\CCC DLL\\" + s) == true)
{
MessageBox.Show("62 bit");
}
else
{
MessageBox.Show("32 bit");
}
}
foreach (string s in Directory.GetFiles(path, "*.ocx").Select(Path.GetFileName))
_Regfiles.Add(Application.StartupPath + "\\CCC DLL\\" + s);
foreach (string filepath in _Regfiles)
{
obj = new DLLHelper(filepath);
obj.DumpToFile(RootPath + obj.GetDLLName());
}
MessageBox.Show("Register Colmpleted");
}
catch (Exception ex)
{
//Console.WriteLine("Is64BitOperatingSystem throws the exception: {0}",
// ex.Message);
MessageBox.Show(ex.Message.ToString());
}
}
public void Registar_Dlls(string filePath)
{
try
{
//'/s' : Specifies regsvr32 to run silently and to not display any message boxes.
//string arg_fileinfo = "/s" + " " + "\"" + filePath + "\"";
string arg_fileinfo = RootPath +"\regsvr32.exe"+" "+ "/s" + " " + "\"" + filePath;
Process reg = new Process();
//This file registers .dll files as command components in the registry.
reg.StartInfo.FileName = "cmd.exe"; //"regsvr32.exe";
reg.StartInfo.Arguments = arg_fileinfo;
reg.StartInfo.UseShellExecute = false;
reg.StartInfo.CreateNoWindow = true;
reg.StartInfo.RedirectStandardOutput = true;
if (System.Environment.OSVersion.Version.Major >= 6)
{
reg.StartInfo.Verb = "runas";
}
reg.Start();
reg.WaitForExit();
reg.Close();
// MessageBox.Show("Successfully Registered your Ocx files");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
OK, I am working on a program that will automatically download an update if the versions don't match.
The problem now is that it loads the info from an XML file, but it doesn't download the files specified.
Any suggestions to improve the code are welcome as well!
Here is the complete source code:
http://www.mediafire.com/?44d9mcuhde9fv3e
http://www.virustotal.com/file-scan/report.html?id=178ab584fd87fd84b6fd77f872d9fd08795f5e3957aa8fe7eee03e1fa9440e74-1309401561
Thanks in advance for the help!
EDIT
The File to download, specified in Program.cs does not download and the program gets stuck at
currentFile = string.Empty;
label1.Text = "Preparing to download file(s)...";
Thread t = new Thread(new ThreadStart(DownloadFiles)); // Making a new thread because I prefer downloading 1 file at a time
t.Start();
and it start the "Thread t".
Code that seems to be making problems:
UpdateForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.NetworkInformation;
using System.Net;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Xml;
using System.Xml.Linq;
using System.Runtime.InteropServices;
namespace LauncherBeta1
{
public partial class UpdateForm : Form
{
const int MF_BYPOSITION = 0x400;
[DllImport("User32")]
private static extern int RemoveMenu(IntPtr hMenu, int nPosition, int wFlags);
[DllImport("User32")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("User32")]
private static extern int GetMenuItemCount(IntPtr hWnd);
private static WebClient webClient = new WebClient();
internal static List<Uri> uriFiles = new List<Uri>();
internal static Uri uriChangelog = null;
private static long fileSize = 0, fileBytesDownloaded = 0;
private static Stopwatch fileDownloadElapsed = new Stopwatch();
bool updateComplete = false, fileComplete = false;
string currentFile = string.Empty, labelText = string.Empty;
int progbarValue = 0, KBps = 0;
public UpdateForm()
{
IntPtr hMenu = GetSystemMenu(this.Handle, false);
int menuItemCount = GetMenuItemCount(hMenu);
RemoveMenu(hMenu, menuItemCount - 1, MF_BYPOSITION);
InitializeComponent();
XmlDocument xdoc = new XmlDocument();
xdoc.Load("http://raiderz.daregamer.com/updates/app_version.xml");
XmlNode xNodeVer = xdoc.DocumentElement.SelectSingleNode("Version");
FileVersionInfo fileVer = FileVersionInfo.GetVersionInfo(AppDomain.CurrentDomain.BaseDirectory + "lua5.1.dll");
int ver_app = Convert.ToInt32(fileVer.FileVersion.ToString());
int ver_xml = Convert.ToInt32(xNodeVer);
if (ver_xml == ver_app)
{
Application.Run(new Form1());
Environment.Exit(0);
}
else
{
if (ver_xml < ver_app || ver_xml > ver_app)
{
if (uriChangelog != null)
{
label1.Text = "Status: Downloading changelog...";
try
{
string log = webClient.DownloadString(uriChangelog);
log = log.Replace("\n", Environment.NewLine);
txtboxChangelog.Text = log;
}
catch (WebException ex) { }
}
foreach (Uri uri in uriFiles)
{
string uriPath = uri.OriginalString;
currentFile = uriPath.Substring(uriPath.LastIndexOf('/') + 1);
if (File.Exists(currentFile))
{
label1.Text = "Status: Deleting " + currentFile;
File.Delete(currentFile);
}
}
currentFile = string.Empty;
label1.Text = "Preparing to download file(s)...";
Thread t = new Thread(new ThreadStart(DownloadFiles)); // Making a new thread because I prefer downloading 1 file at a time
t.Start();
}
else
{
//MessageBox.Show("Client is up to date!");
Application.Run(new Form1());
Environment.Exit(0);
}
}
}
private void DownloadFiles()
{
foreach (Uri uri in uriFiles)
{
try
{
fileComplete = false;
fileDownloadElapsed.Reset();
fileDownloadElapsed.Start();
string uriPath = uri.OriginalString;
currentFile = uriPath.Substring(uriPath.LastIndexOf('/') + 1);
webClient.DownloadFileAsync(uri, currentFile);
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCompleted);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressChanged);
while (!fileComplete) { Thread.Sleep(1000); }
}
catch { continue; }
}
currentFile = string.Empty;
updateComplete = true;
}
void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progbarValue = e.ProgressPercentage;
fileSize = e.TotalBytesToReceive / 1024;
fileBytesDownloaded = e.BytesReceived / 1024;
if (fileBytesDownloaded > 0 && fileDownloadElapsed.ElapsedMilliseconds > 1000)
{
KBps = (int)(fileBytesDownloaded / (fileDownloadElapsed.ElapsedMilliseconds / 1000));
}
labelText = "Status: Downloading " + currentFile +
"\n" + fileBytesDownloaded + " KB / " + fileSize + " KB - " + KBps + " KB/s";
}
void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
progbarValue = 0;
fileComplete = true;
}
/// <summary>
/// Returns file size (Kb) of a Uri
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
private long GetFileSize(Uri uri)
{
try
{
WebRequest webRequest = HttpWebRequest.Create(uri);
using (WebResponse response = webRequest.GetResponse())
{
long size = response.ContentLength;
return size / 1024;
}
}
catch { return 1; }
}
private void timerMultiPurpose_Tick(object sender, EventArgs e)
{
if (updateComplete == true)
{
updateComplete = false;
label1.Text = "Status: Complete";
progressBar1.Value = 0;
MessageBox.Show("Update complete!!");
Application.Run(new Form1());
Environment.Exit(0);
}
else
{
progressBar1.Value = progbarValue;
label1.Text = labelText;
}
}
private void UI_FormClosing(object sender, FormClosingEventArgs e)
{
Environment.Exit(0);
}
}
}
Relevant code from Program.cs:
System.Threading.Thread.Sleep(1000); // Give the calling application time to exit
XmlDocument xdoc = new XmlDocument();
xdoc.Load("http://raiderz.daregamer.com/updates/app_version.xml");
XmlNode xNodeVer = xdoc.DocumentElement.SelectSingleNode("Loc");
string ver_xml = Convert.ToString(xNodeVer);
args = new string[2];
args[0] = "Changelog=http://raiderz.daregamer.com/updates/changelog.txt";
args[1] = "URIs=" + ver_xml;
if (args.Length == 0)
{
MessageBox.Show("Can not run program without parameters", "Error");
return;
}
try
{
foreach (string arg in args)
{
if (arg.StartsWith("URIs="))
{
string[] uris = arg.Substring(arg.IndexOf('=') + 1).Split(';');
foreach (string uri in uris)
{
if (uri.Length > 0)
{
UpdateForm.uriFiles.Add(new Uri(uri));
}
}
}
else if (arg.StartsWith("Changelog="))
{
UpdateForm.uriChangelog = new Uri(arg.Substring(arg.IndexOf('=') + 1));
}
}
}
catch { MessageBox.Show("Missing or faulty parameter(s)", "Error"); }
I've not downloaded or reviewed your code, but if this is all C# based and on the v2.0 framework or higher you may want to check in to using ClickOnce. It will handle much of the auto updating for you and even allow users to continue using the program if they are offline and unable to connect to your update server.