Windows Update API Memory Leak in Code - c#

I am developing an application in C# to aid in a process that my company uses to configure new PCs before adding them to our domain, for offices all around the country. I am currently at a phase where I need to automate Windows Updates without any feedback from the user.
I have all of the Windows Update code put together in a console application. But I noticed when there are a LOT of updates (60 to 100+) the TrustedInstaller process ends up using over 1.5GB of RAM (after about 1hr+ during the install process), although the installation of the updates eventually does finish (2-4 hours later) I feel like 1.5GB of physical memory is just too much (even though this will be the only productive process running at the time).
In the interest in ensuring my code runs optimally would someone mind taking a look for me? I am very new to the Windows Update API(wuapi.dll) and there is very little documentation on the internet.
Here is the snippet of code (at the very bottom of my "program" class) that initiates and runs the installation of downloaded updates:
using WUApiLib
Console.WriteLine(Environment.NewLine + Environment.NewLine + "Installing Updates...");
IUpdateInstaller installer = uSession.CreateUpdateInstaller();
installer.Updates = updatesToInstall;
IInstallationResult installationRes = installer.Install();
List<object> successUpdates = new List<object>();
Console.Clear();
for (int i = 0; i < updatesToInstall.Count; i++)
{
if (installationRes.GetUpdateResult(i).HResult == 0)
{
Console.WriteLine("Installed: " + updatesToInstall[i].Title);
successUpdates.Add(i);
}
else
{
Console.WriteLine("Failed: " + updatesToInstall[i].Title);
}
}
Console.WriteLine(Environment.NewLine + Environment.NewLine +
"{0} out of {1} updates installed successfully!",successUpdates.Count() ,updatesToInstall.Count);
And below is my entire code for searching, downloading, and installing the updates (Console.Readkey() methods are in there simply for testing):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WUApiLib;
using System.Management;
namespace WUConsole
{
class Program
{
static void Main()
{
Console.WriteLine(Environment.NewLine + Environment.NewLine +
"Checking for Windows Updates...");
try
{
UpdateSession uSession = new UpdateSession();
IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
ISearchResult uResult = uSearcher.Search("IsInstalled=0 and Type='Software' and BrowseOnly=0");
Console.Clear();
Console.Write("Available Updates:" + Environment.NewLine + Environment.NewLine);
foreach (IUpdate update in uResult.Updates)
{
Console.WriteLine("-" + update.Title);
}
if (uResult.Updates.Count == 0)
{
Console.Clear();
Console.WriteLine(Environment.NewLine + Environment.NewLine + "Windows is up to date!");
Console.ReadKey();
Environment.Exit(0);
}
int updateCount = uResult.Updates.Count;
if (updateCount == 1)
{
Console.WriteLine(Environment.NewLine + Environment.NewLine +
"Finished searching for updates. {0} update found.", updateCount);
}
else
{
Console.WriteLine(Environment.NewLine + Environment.NewLine +
"Finished searching for updates. {0} updates found.", updateCount);
}
Console.ReadKey();
Console.Clear();
if (updateCount == 1)
{
Console.WriteLine(Environment.NewLine + Environment.NewLine +
"Downloading {0} Windows Update...", updateCount);
}
else
{
Console.WriteLine(Environment.NewLine + Environment.NewLine +
"Downloading {0} Windows Updates...", updateCount);
}
UpdateDownloader downloader = uSession.CreateUpdateDownloader();
downloader.Updates = uResult.Updates;
downloader.Download();
Console.Clear();
Console.WriteLine(Environment.NewLine + Environment.NewLine + "Updates Downloaded Successfully!");
UpdateCollection updatesToInstall = new UpdateCollection();
foreach(IUpdate update in uResult.Updates)
{
if (update.IsDownloaded)
update.AcceptEula();
updatesToInstall.Add(update);
}
Console.Clear();
Console.WriteLine(Environment.NewLine + Environment.NewLine + "Installing Updates...");
IUpdateInstaller installer = uSession.CreateUpdateInstaller();
installer.Updates = updatesToInstall;
IInstallationResult installationRes = installer.Install();
List<object> successUpdates = new List<object>();
Console.Clear();
for (int i = 0; i < updatesToInstall.Count; i++)
{
if (installationRes.GetUpdateResult(i).HResult == 0)
{
Console.WriteLine("Installed: " + updatesToInstall[i].Title);
successUpdates.Add(i);
}
else
{
Console.WriteLine("Failed: " + updatesToInstall[i].Title);
}
}
Console.WriteLine(Environment.NewLine + Environment.NewLine +
"{0} out of {1} updates installed successfully!",successUpdates.Count() ,updatesToInstall.Count);
Console.ReadKey();
Console.WriteLine(Environment.NewLine + Environment.NewLine + "1");
Console.ReadKey();
System.Diagnostics.Process.Start("shutdown", "/r /t 0");
}
catch (Exception e)
{
Console.Clear();
Console.WriteLine(Environment.NewLine + Environment.NewLine + "Windows Update failed: " + e.Message);
Console.ReadKey();
}
}
}
}
Any feedback/ pointers on this would be greatly appreciated, as I know there is not much documentation out there.
Thanks so much!

Related

Getting the Bluetooth version of a device

I need validate that a Bluetooth LE 5.0 device is connected to a computer. I have been reviewing all the properties I can query for a device but I haven't found one that contains the Bluetooth version of the device. Can this be done using UWP or any other method?
This is the code I am using to explore the data I can get using UWP:
string aqsFilter = "System.Devices.DevObjectType:=5 AND (System.Devices.Aep.ProtocolId:=\"{BB7BB05E-5972-42B5-94FC-76EAA7084D49}\" OR System.Devices.Aep.ProtocolId:=\"{E0CBF06C-CD8B-4647-BB8A-263B43F0F974}\") AND (System.Devices.Aep.IsConnected:=System.StructuredQueryType.Boolean#True OR System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#False)";
string[] requestedProperties = {
"System.Devices.Aep.Category",
"System.DeviceInterface.Bluetooth.DeviceAddress",
"System.DeviceInterface.Bluetooth.Flags",
"System.Devices.Aep.Bluetooth.Le.AddressType",
"System.Devices.Aep.Bluetooth.Le.Appearance",
"System.Devices.Aep.Bluetooth.Le.Appearance.Category",
"System.Devices.Aep.Bluetooth.Le.Appearance.Subcategory",
"System.Devices.Aep.DeviceAddress",
"System.Devices.AepService.ServiceClassId",
"System.Devices.Aep.ProtocolId",
"System.Devices.AepService.ProtocolId"
};
DeviceInformationCollection ConnectedBluetoothDevices = await DeviceInformation.FindAllAsync(aqsFilter, requestedProperties); //aqsFilter
foreach (DeviceInformation connectedBluetoothDevice in ConnectedBluetoothDevices)
{
Console.WriteLine(connectedBluetoothDevice.Name);
Console.WriteLine(" " + connectedBluetoothDevice.Id);
Console.WriteLine(" " + connectedBluetoothDevice.Kind.ToString());
Console.WriteLine(" " + connectedBluetoothDevice.Properties.Count);
foreach (KeyValuePair<string, object> property in connectedBluetoothDevice.Properties)
{
if (property.Value != null && property.Value.GetType().IsArray)
{
String[] array = (String[])property.Value;
Console.WriteLine(" " + property.Key + " = " + array[0]);
}
else
{
Console.WriteLine(" " + property.Key + " = " + property.Value);
}
}
}

C# Managing threads in console application

Good day everyone,
I need to say firstly, that I am not a C# developer in anyway, I have been tasked from my boss to "Make it work".
What I want is to have a thread that will spin off, not interrupt main(), call a function CcnDirSearch() and re perform this action after a certain amount of time.
My code currently runs in console about 1 time (sometimes 6 times) and then stops. I think the threads(or something like this) are ending before the function is completing.
Here is my code:
public int Run()
{
Task.Factory.StartNew(() => CcnDirFireAway());
...
...
//continues main();
>
public void CcnDirFireAway()
{
if (ScanDir != "")
{
Console.WriteLine("Starting Initial Scan on Directory: " + ScanDir + "\n\n\n");
TimerCallback tmCallback = CheckEffectExpiry;
Timer timer = new Timer(tmCallback, "test", 1000, 1000);
}
}
>
public void CheckEffectExpiry(object objectInfo)
{
//TODO put your code
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(DateTime.Now + " Starting Scan.....\n");
Console.ForegroundColor = ConsoleColor.White;
//Here is a call to my function that I want to call.
// I noticed that If I don't call it the programs continues to run harmoniously
Searcher.CcnDirSearch(ScanDir);
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(DateTime.Now + " Finished Scan.....\n");
Console.ForegroundColor = ConsoleColor.White;
}
>
Here is the code of the function I need to call off .
public static void CcnDirSearch(string sDir)
{
try
{
foreach (string file in Directory.EnumerateFiles(sDir, "*.*", SearchOption.AllDirectories))
{
using (var stream = File.OpenRead(file))
{
// Console.WriteLine(DateTime.Now + " Checking File : " + file);
bool Mcard = Searcher.CCNSearch(file, De.Thekid.INotify.Runner.MASTERCARD, false);
bool VCARD = Searcher.CCNSearch(file, De.Thekid.INotify.Runner.VISA, false);
bool ACARD = Searcher.CCNSearch(file, De.Thekid.INotify.Runner.AMEX, false);
if (Mcard)
{
Console.WriteLine(DateTime.Now + " MasterCard Number Found In File >> " + file);
//Inotifywatch.EventForward.UDPSend(512, RServer, ("<30>" + DateTime.Now + " MasterCard Number Found In File >> " + fullpath+ "\n"));
Logger.WriteEvent(DateTime.Now + " MasterCard Number Found In File >> " + file + "\n");
}
else if (VCARD)
{
Console.WriteLine(DateTime.Now + " Visa Card Number Found In File >> " + file);
//Inotifywatch.EventForward.UDPSend(512, RServer, ("<30>" + DateTime.Now + " Visa Card Number Found In File >> " + fullpath+ "\n"));
Logger.WriteEvent(DateTime.Now + " Visa Card Number Found In File >> " + file + "\n");
}
else if (ACARD)
{
Console.WriteLine(DateTime.Now + " AMEX Card Number Found In File >> " + file);
//Inotifywatch.EventForward.UDPSend(512, RServer, ("<30>" + DateTime.Now + " AMEX Card Number Found In File >> " + fullpath+ "\n"));
Logger.WriteEvent(DateTime.Now + " Amex Card Number Found In File >> " + file + "\n");
}
}
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
Console.Write("Finished the Search\n");
}
You could use a DispatcherTimer to call a function on a given time interval, then in that function create and start a new Thread in which you execute your function.
public static void Main(string[] args)
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(5000);;
timer.IsEnabled = true;
timer.Tick += OnTimerTick;
}
private void OnTimerTick(object sender, EventArgs e)
{
var thread = new Thread(new ThreadStart(()=>yourMethodToCall()));
thread.Start();
}
I want to Thanks everyone for all your help. I found a work around that worked for me.
As I said before , I am not a C# developer (I play one on T.V) so I am certain there are somethings where this code base can be improved .
If someone can write a better answer, I will happily accept it.
I just decided to launch the code differntly .
Timer x = new Timer(state => CheckEffectExpiry(1), null, 5000 /* When to start*/, 300000 /* when to retry */);
>
public void CheckEffectExpiry(object objectInfo)
{
//I hate C#'s way of accessing variables and such .
//So I am doing this...
Console.Write(DateTime.Now + " I was hit\n");
if (lockf == 1)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(DateTime.Now + " Starting Scan.....\n");
Console.ForegroundColor = ConsoleColor.White;
lockf = 0;
Searcher.CcnDirSearch(ScanDir);
lockf = 1;
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(DateTime.Now + " Finished Scan.....\n");
Console.ForegroundColor = ConsoleColor.White;
}
}

Getting HDD info only returns C drive info none others. c#

I am putting together a program that pulls out a bunch of info from a PC and sends it to a server. I am currently working on trying to pull hdd info from the pc that has multiple drives but i can only get it to work with the first drive. Below is the code that pulls out the actual drive info and below that is the code that writes it out to console:
public static string CurrentDiskUsage()
{
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
try
{
if (drive.IsReady)
{
double result = 100 * (double) drive.TotalFreeSpace / drive.TotalSize;
result = Math.Round(result, 2, MidpointRounding.AwayFromZero);
string driveInformation = null;
driveInformation += drive.Name + "\n" + drive.DriveFormat + "\n" + "Drive total size: " + FormatBytes(drive.TotalSize) + "\n" + "Drive total free space: " + FormatBytes(drive.TotalFreeSpace) + "\n" + "Free space as percentage: " + result + "% \n ";
return driveInformation;
}
}
catch (Exception e)
{
return "Fail";
Console.WriteLine(e);
}
}
return "Fail";
}
Writes info to console
String[] Content = new string[7];
Content[0] = reportFunctions.GetOsName();
Content[1] = reportFunctions.IsSoftwareInstalled();
Content[2] = reportFunctions.CurrentLoggedInUser();
Content[3] = reportFunctions.GetPcName();
Content[4] = reportFunctions.CurrentDiskUsage();
int i = 0;
while (i < 6)
{
Console.WriteLine(Content[i]);
i++;
}
}
At the end of the first loop you have "return "Fail";"
Remove this line as it is blocking further effort. You probably also want to remove the return from the exception as if your CD drive say drive D isnt ready your code will stop, and not continue too
EDIT: instead of the returns - as you also try to return a string of drive info - just write this data out to console. Return means stop doing what Im doing now and go back to whatever ran me.
Your code needs to look more like this (PS you should also use Environment.NewLine not \n as this always returns the correct linefeed for the OS)
public static string CurrentDiskUsage()
{
String driveInformation =""; //your code overwrote this with each loop
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
try
{
if (drive.IsReady)
{
double result = 100 * (double) drive.TotalFreeSpace / drive.TotalSize;
result = Math.Round(result, 2, MidpointRounding.AwayFromZero);
driveInformation += drive.Name + Environment.NewLine + drive.DriveFormat + Environment.NewLine + "Drive total size: " + FormatBytes(drive.TotalSize) + Environment.NewLine + "Drive total free space: " + FormatBytes(drive.TotalFreeSpace) + Environment.NewLine + "Free space as percentage: " + result + "% "+Environment.NewLine;
}
}
catch (Exception e)
{
DriveInformation+="Fail:"+Drive.Name+Environment.NewLine+e.Message;
}
}
return driveInformation;
}

C# out of memory with file

I'm getting a OutOfMemory exception when running the following code, it happens on the File.ReadLines line, it processes most files fine until it hits larger files.
It's consistantly using tons of memory and cpu during the whole process though.
The file it crashed on is only 156,000KB, which is 156mb
static void Main(string[] args)
{
Console.CursorVisible = false;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine();
Console.WriteLine(" [" + DateTime.Now.ToShortTimeString() + "]" + " Connected to the Cassandra Database");
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.White;
string filepath = #"C:\Users\admin\Desktop\wecrack lists";
DirectoryInfo directory = new DirectoryInfo(filepath);
int fileCount = 0;
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("cracking");
var collection = database.GetCollection<Password>("passwords");
foreach (var file in directory.GetFiles("*"))
{
fileCount++;
Console.WriteLine(" [" + DateTime.Now.ToShortTimeString() + "]" + " Working through file: {" + file + "} {" + fileCount + "/" + directory.GetFiles("*").Count() + "}");
List<Password> entitys = new List<Password>();
foreach (string line in File.ReadLines(filepath + #"\" + file.ToString()))
{
entitys.Add(new Password { password = line });
}
collection.InsertManyAsync(entitys);
}
Console.WriteLine();
Console.WriteLine(" [" + DateTime.Now.ToShortTimeString() + "]" + " Finished inserting records, press any key to get the count.");
Console.ReadKey(true);
while (true)
{
Console.ReadKey(true);
}
}
Try batching your updates. That way you won't have all that data in memory at the same time. It may also help you not totally lock up your database.
...
foreach (var file in directory.GetFiles("*"))
{
fileCount++;
Console.WriteLine(" [" + DateTime.Now.ToShortTimeString() + "]" + " Working through file: {" + file + "} {" + fileCount + "/" + directory.GetFiles("*").Count() + "}");
System.IO.StreamReader file = new System.IO.StreamReader(filepath + #"\" + file.ToString());
while(!file.EndOfStream)
{
int passwordBatchCount = 0;
List<Password> entitysBatch = new List<Password>();
while ((string line = file.ReadLine()) != null && passwordBatchCount < BATCH_SIZE)
{
entitysBatch.Add(new Password { password = line });
passwordBatchCount++;
}
collection.InsertManyAsync(entitysBatch);
}
file.Close();
}
}
...

Permissions on a folder

I have been looking for some time now and have not been able to find this. How can I set my program up to write or update a file from multiple users but only one group is allowed to open the read what is in the folder?
class Log_File
{
string LogFileDirectory = #"\\server\boiseit$\TechDocs\Headset Tracker\Weekly Charges\Log\Log Files";
string PathToXMLFile = #"\\server\boiseit$\scripts\Mikes Projects\Headset-tracker\config\Config.xml";
string AdditionToLogFile = #"\Who.Did.It_" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ".txt";
XML XMLFile = new XML();
public void ConfigCheck()
{
if (!File.Exists(PathToXMLFile))
{
XMLFile.writeToXML(PathToXMLFile, LogFileDirectory + AdditionToLogFile);
}
}
public void CreateLogFile()
{
if (Directory.GetFiles(LogFileDirectory).Count() == 0)
{
XMLFile.writeToXML(PathToXMLFile, LogFileDirectory + AdditionToLogFile);
CreateFileOrAppend("");
}
else if (!File.Exists(XMLFile.readingXML(PathToXMLFile)))
{
XMLFile.writeToXML(PathToXMLFile, LogFileDirectory + AdditionToLogFile);
CreateFileOrAppend("");
}
else
{
FileInfo dateOfLastLogFile = new FileInfo(XMLFile.readingXML(PathToXMLFile));
DateTime dateOfCreation = dateOfLastLogFile.CreationTime;
if (dateOfLastLogFile.CreationTime <= DateTime.Now.AddMonths(-1))
{
XMLFile.writeToXML(PathToXMLFile, LogFileDirectory + AdditionToLogFile);
CreateFileOrAppend("");
}
}
}
public void CreateFileOrAppend(string whoDidIt)
{
using (IsolatedStorageFile storage = IsolatedStorageFile.GetStore((IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly | IsolatedStorageScope.User), null, null))
{
using (StreamWriter myWriter = new StreamWriter(XMLFile.readingXML(PathToXMLFile), true))
{
if (whoDidIt == "")
{
}
else
{
myWriter.WriteLine(whoDidIt);
}
}
}
}
This is my path where it needs to go. I have the special permission to open and write to the folder but my co workers do not. I am not allow to let them have this permission.
If I where to set up a database how would i change this code
LoggedFile.CreateFileOrAppend(Environment.UserName.ToUpper() + "-" + Environment.NewLine + "Replacement Headset To: " + AgentName + Environment.NewLine + "Old Headset Number: " + myDatabase.oldNumber + Environment.NewLine + "New Headset Number: " + HSNumber + Environment.NewLine + "Date: " + DateTime.Now.ToShortDateString() + Environment.NewLine);
I need it to pull current user, the agents name that is being affected the old headset and the new headset, and the time it took place.
While you create file, you have to set access rules to achieve your requirements. .
File.SetAccessControl(string,FileSecurity)
The below link has example
https://msdn.microsoft.com/en-us/library/system.io.file.setaccesscontrol(v=vs.110).aspx
Also the "FileSecurity" class object, which is an input parameter, has functions to set access rules, including group level control.
Below link has example
https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesecurity(v=vs.110).aspx
This question will be opened under a new question since I am going to take a different route for recording the data I need Thank you all for the help

Categories

Resources