#176648 - mymateo - Tue Sep 06, 2011 5:04 am
Hey all, it's been a LOOOONG time since I've been here. Back in the day I knew enough about coding in C to write some fairly simple stuff for the GBA, and now I'm branching that knowledge into new territory... with limited success.
I'm using Visual C++ 2010 Express and trying DESPERATELY to get certain portions of it to work. Unfoprtunately, I might as well have picked a programming language out of a hat to use for this project I'm working on because it is soooo foreign to what I recall using to make games.
Of course, a lot of the programming is actually using .NET libraries, so that could explain a lot of it.
So, anyways, here's the situation. I'm trying to write a program that, amongst other things (which ARE working), will automate downloading and installing updates from Windows Updates, then reboot, then pick up installing more updates until they're all been installed, and all without requiring anything from the user. Basically, you click "go" and come back a few hours later to find your computer is completely set up and up to date. This will make windows reinstallations MUCH nicer.
The exact problem I'm having is getting the program to actually work with the wuapi.h header file to actually set up the functions required. Storing progress and auto-launching the program on reboot are no problem, it's just commanding the updates to install. Though as you will see in my sample code I'm starting small: just trying to read one simple setting is thwarting me!
Now, you might as well treat me as a n00b here, 'cause like I say it's been a LONG time since I've done any real coding, and this is totally alien to what I'm used to. (My native programming language is actually Pascal, but Delphi was neither cheap nor appealing).
Here's one snippet of code I've used, just to even try to read basic settings about Windows Updates. In this example, reading the time the automatic updates are set to and displaying an error if it fails.
Code: |
long ScheduledTime;
IAutomaticUpdatesSettings *MySettings;
long TimeResult = MySettings->get_ScheduledInstallationTime(&ScheduledTime);
if (TimeResult != S_OK)
{
MessageBox::Show( this, "Failed to read time!", "All Your Base", MessageBoxButtons::OK);
} |
This compiles just fine, I just get a warning that the variable "MySettings" is uninitialized. Part of the issue is that the only real documentation on the IAutomaticUpdatesSettings type is written by Microsoft, and there's NO example source code on how to properly initialize the variable. It seems to me that using the get_ScheduledInstallationTime is probably failing because of this. That's where I'm stuck.
Also, when I run the program I get an error "An unhandled exception of type 'System.NullReferenceException' occurred in myapp.exe
Additional information: Object reference not set to an instance of an object."
This error may help in identifying where I've been massively stupid. I'm afraid once I discover (or if someone here blatently points out) what I've done wrong I'll feel like a class fool. I'm willing to make that sacrifice!
Also, if it helps, there are two other code snippets of things I've tried, all with the same warnings and errors. Again, these just use the wuapi.h header file which contains all of the definitions.
This basically just refreshes the current settings into the MySettings variable. Ideally, wouldn't THIS initialize the variable?
Code: |
IAutomaticUpdatesSettings *MySettings;
MySettings->Refresh(); |
And again here, all this is supposed to do is launch the Windows Updates settings dialog.
Code: |
IAutomaticUpdates *Updates;
Updates->ShowSettingsDialog(); |
I've even found source code for a visual basic script that is supposed to basically just tell you whether Automatic Updates are turned on or off, and I've tried to translate it into C++ to no avail.
I hope someone here who still reads these old forums knows enough about this to lead me in the right direction.
Thanks in advance for any help or suggestions!
#176649 - Dwedit - Tue Sep 06, 2011 4:16 pm
You just created a pointer of type "object that inherits IAutomaticUpdatesSettings", and not assigned anything to it. So no wonder you get errors about MySettings being uninitialized. When you see a type like IAutomaticUpdatesSettings, that's actually an interface. You can't create instances of that type. You need to play "Guess the class", and you need to figure out what object type is actually assigned to that interface type. Then you can create an instance of the type with the "new" operator.
I never understood why anyone in their right mind would use Managed C++ (now called C++/CLI). You get the worst of both worlds, slow performance, outdated C++ syntax, and weird language extensions just to make it work with .NET. As far as I know, it's only used by people who inherited a mountain of old C++ code and want to use .NET features.
In managed C++, you usually use the ^ for managed references to objects instead of using pointer syntax *. So you would use syntax like "MyClass ^myObject = gcnew MyClass(argument1,argument2);" for about 95% of all objects you'd create.
Don't want all this stuff in your code? Then use standard C++ that compiles to native code, not some special Microsoft-specific C++ that compiles to CLI code.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#176650 - mymateo - Wed Sep 07, 2011 4:21 am
Yeah, it's my complete lack of knowledge or experience working with interfaces that has me stumped. As far as why I'd go with Managed C++, I guess it was just a bad decision.
My thought process? "I need a free programming tool that will allow me to quickly bang out a GUI with no effort, and a language that I've used before, and something that can work with the registry and Windows updates. Let's see... Visual C++ Express, sounds good!" Oh boy.
Like I mentioned before, this whole thing is as alien to me as if I just picked a random programming language out of a hat. I might as well have attemped to prorgam in assembly, or binary for that matter, for how much sense it all makes to me.
I've tried looking up some information about how interfaces are made, but very little comprehensible information seems to be available. Sadly, this seems to be a case of learning to fly before I can walk as everything assumes a fair bit of knowledge that I don't possess. And I'm certain that in the end it's probably only a couple of lines of code that it will equate to to get the ball rolling, but damned if I will figure it out anytime soon.
I appreciate your help, and I'll keep looking. I'll post again if I find anything more enlightening. I'm trolling the header files to try and gleam some insight on where things are coming from, and I'll keep trying to find tutorials or sample code on working with interfaces to try and help me with this one.
Darn microsoft.
#176651 - mymateo - Wed Sep 07, 2011 5:46 am
OK, maybe I'm just ranting now, but I've spent literally HOURS looking up information on how to use interfaces within the last couple of days (figuring the lack of information about them is my issue), and I keep running into the same bloody thing.
Every sample code I find does not apply!
I have found several samples of using Interfaces, and I have tried to adapt their code to the stupid IAutomaticUpdates Interface, and I'm coming up with this conclusion:
The interface doesn't DO anything!
Everywhere I look I seem to notice a trend: an interface appears to only be a container, but holds no data (which was explicit on one page at least) and I can only infer that it doesn't hold anything else either.
Someone PLEASE correct me if I'm wrong! Otherwise I'm going to bang my head on a wall for a few more days and get nowhere, except to find I've been chasing ghosts.
I'm using the wuapi.h header, which holds the IAutomaticUpdates interface.
Answer me this:
Is there any reason to believe that there are any functions or procedures (sorry, using Pascal terms) that will accomplish a task and send a result of any kind? Or are Interfaces just husks; shells which you enter your own code into?
I'm going crazy here! None of this makes any dang sense to me! Even sites that spell it out in plain english don't apply! I've tried to set up a class to use IAutomaticUpdates, but I only got so far before I realized that it wasn't going to help when I got to the part about entering my own code. Isn't that what the .NET framework is supposed to be for? To supply some base code so that it's easier to code for common tasks? ARGH! I feel like screaming out loud!
(Sorry, I know it doesn't help anyone but me to vent... I think I'll just go cry for a little while, then it's back to that lovely dent I've put in the wall with my head...)
#176652 - fincs - Wed Sep 07, 2011 12:54 pm
It's a COM object, you have to do a lot of stuff to use such objects. Gotta love Microsoft.
Untested:
Code: |
IAutomaticUpdates* pUpdates;
// Initialize COM, this might not be needed since you're using the .NET framework
if (SUCCEEDED(CoInitialize(NULL))
{
// Place here COM-using code
// Create AutomaticUpdates object
if (SUCCEEDED(CoCreateInstance(CLSID_AutomaticUpdates, NULL, CLSCTX_INPROC, IID_IAutomaticUpdates, (void**) &pUpdates)))
{
// Now you can use your object
pUpdates->ShowSettingsDialog();
// Delete the object
pUpdates->Release();
}
// Uninitialize COM
CoUninitialize(NULL);
}
|
#176653 - keldon - Wed Sep 07, 2011 1:51 pm
http://www.charlespetzold.com/pw5/
The above book shows you how to use Win32 to develop Windows applications. But one question, when you say quickly bang out a GUI with no effort, what exactly do you mean.
Is my understanding right, that you just want to be able to draw/render to a window? If so, that can be done in Visual Studio Express, without the COM objects and with very little effort.
Could you describe you brief intentions?
#176656 - Dwedit - Wed Sep 07, 2011 6:16 pm
Use C# if you want to bang out a program, not C++.
Visual C# express is free from Microsoft, and does almost everything the full version does.
What it doesn't do: profiling, code analysis tools, mixed-langauge multi-project solutions.
If you ever used Visual Basic a while ago, you probably know most of how to use Windows.Forms. Only major difference is that some things that used to be strings now got promoted to the Object type, such as items in a list box.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#176660 - mymateo - Thu Sep 08, 2011 2:53 am
@Keldon
What I mean by making a GUI with no effort is that with a couple of clicks I had the entire main window laid out with buttons, check boxes, labels and a progress bar. That part took me all of 5 minutes because I didn't have to manually define each button and where to place it, it was click-and-drag. THAT part worked out well for me!
Brief intentions: a window that will let you select options for setting up your computer. For example, I like to install and try out a lot of programs. Most of them entertain me for a little while, others kinds screw things up, so I often like to wipe my computer and reload it. Setting it back up is a pain, and I don't like using disk images because I always like everything to be freshly up-to-date. So I want to make a program that makes it very easy for myself: I check boxes for which options I would want (homepage, which programs to install, set my background, etc) and then I click "GO", walk away, and come back in a couple of hours to see everything is installed, my options are set, and Windows is all up to date with minimal "updates on updates that updated a patch that fixed a bug introduced by an update that patched a feature that was supposed to update an update" (which is what happens if you let Microsoft patch your Windows to death - but every so often M$ will release an update similar to a service pack that simply updates a subfeature to the most recent version without the need for patching and re-patching). So the GUI was the easy part, most of the other options were a cinch to figure out, but these darn updates have got me stumped. After this it's going to be interesting to figure out an automated install for my Office and Norton that will let me plop the product key in at the start and have it automatically install and activate... might just have to let it install and require activation at the end, but my ultimate dream is a two-click approach to Windows re-isntallation nirvana.
@fincs
Thanks for the code! I'll give it a try, and if it works then it will really help me to understand how to use this stuff better. I am very specific in saying that I will have a better understanding of USING this stuff, not understanding the stuff itself. Hey, if it gets this project moving a step forward then that's great! I'll let you know if it worked for me. If it didn't work, but helped me get close enough to MAKE it work, then I'll post the modified code.
@Dwedit
I've never used Visual basic. I seem to recall using Basic back in the days of Windows 3.1 to play a little tune... nothing since then. I've come across a lot of C# code while trying to find ways to get this project of mine completed, and it seems like most of the code I already have would take minimal work to adapt it, but I'm not sure I want to take on that extra work of converting code when I feel like I'm SOOOO close!
Thanks all for your help! Wish me luck, I may have another long evening ahead of me!
#176661 - mymateo - Thu Sep 08, 2011 3:01 am
@fincs
Well with minimal changes to the code you provided I was able to clear out the initial compiler errors. Missing a ")" in the first line and the CoUninitialize didn't like having an argument passed so I removed the NULL. Now I just have a few *linker* errors to resolve before I find out how well it works, but it's definitely giving me hope yet!
Thank you so much for giving me a new direction! How come not a single page I've looked at has mentioned anything about COM objects?? Yeesh. Thank goodness for smart, helpful people in this world! I owe more than a few people on this forum a beer or coke or whatever their poison is.
#176662 - mymateo - Thu Sep 08, 2011 4:20 am
WoooooOoOOOoOOoOOOoOooOOOOOooO HOOOO!!!!!!!!!!!!
Yeah! Friggin' YEAH YEAH YEAH! Oh hecks yeah!
*ahem*
@fincs
Thank you SOOOoOoOoOOO much! With those two edits I had to make (the bracket and removing the second "NULL") your code worked PERFECTLY!
@everybody following who may be interested in a status update
In order to resolve the linker errors I had to find a few other pages before I came across enough different errors with different solutions in order to piece together what was causing my linker errors.
So, for those who may ever come across this (give Google bots a little while to cache this page and show it up in resutls) I had missed a file. But there are a few other things that seem needed to be in place (which I already had, but others may not be so lucky).
First: Use /CLR in both your general and C++ Common Language Runtime Support properties. Not /CLR:Pure and not in just one or the other (both should match).
Second: Don't just include the .h file, you need to go to project -> properties -> configuration properties -> Linker -> Addition Dependencies and add the Wuguid.lib
Third: A knowledge of COM objects (or at least how to scrap the code together with awesome help from people much smarter than you) is a must!
Now I get to play with this and the IAutomaticUpdatesSettings interface to set things up and run 'em!
Oh boy I am so stoked! If we hadn't just lost an income in our house I would be sending you cold hard cash my friend!
#176711 - mymateo - Fri Sep 16, 2011 6:40 am
Hey fincs, could I pick your brain a little more?
Working away at my project, I had a little success with that code you gave me, and I found out that the IAutomaticUpdates wasn't the interface I needed, and I thought it was IAutomaticUpdatesSettings that might be my next step, but I couldn't get that to work because it didn't have a CLSID of it's own...
To keep it more to the point, I have finally found (and had some success) with finding what I need to do to get updates. I've got my code far enough that it will actually check for updates (at least, I THINK it's checking for updates... the program becomes unresponsive for a few moments while it's running the code that SAYS it checks for updates), but trying to go the next step is causing me some issues, and I can't figure out why.
First, the error I'm getting. Quote: |
An unhandled exception of type 'System.NullReferenceException' occurred in my.exe
Additional information: Object reference not set to an instance of an object. |
Normally, this means that I have to use CoCreateInstance to resolve the issue. I ran into that a couple of times before my app would get updates.
Here's the relevant code:
Code: |
IUpdateSession* uSession;
IUpdateSearcher* uSearcher;
ISearchResult* uResult;
IUpdateCollection* uUpdateCollection;
IUpdateDownloader* uUpdateDownloader;
if (SUCCEEDED(CoInitialize(NULL)))
{
if (SUCCEEDED(CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC, IID_IUpdateSession, (void**) &uSession)))
{
UpdateResults("Update session started");
uSession->CreateUpdateSearcher(&uSearcher);
UpdateResults("Update Searcher created, Searching for results");
uSearcher->Search(TEXT("IsInstalled=0 and Type='Software'"), &uResult);
if (SUCCEEDED(CoCreateInstance(CLSID_UpdateDownloader, NULL, CLSCTX_INPROC, IID_IUpdateDownloader, (void**) &uUpdateDownloader)))
{
if (SUCCEEDED(CoCreateInstance(CLSID_UpdateCollection, NULL, CLSCTX_INPROC, IID_IUpdateCollection, (void**) &uUpdateCollection)))
{
uSession->CreateUpdateDownloader(&uUpdateDownloader);
uUpdateDownloader->get_Updates(&uUpdateCollection);
long NumUpdates = 0;
uUpdateCollection->get_Count(&NumUpdates);
for (long myx = 1; myx <= NumUpdates; myx++)
{
UpdateResults("Another update found!");
}
uUpdateCollection->Release();
}
uUpdateDownloader->Release();
}
uResult->Release();
uSearcher->Release();
uSession->Release();
}
CoUninitialize();
} |
As-is, this crashes the program and gives me the error above. When I comment out the line "uUpdateDownloader->get_Updates(&uUpdateCollection);" then no more crash (however, it's unable to count the number of updates, which I attribute to having the get_Updates part removed).
Oddly enough, the uUpdateCollection->Release(); line was also crashing my app for a little while, so I took it out and even tried moving it around a little, couldn't get it figured out, then I put it back in to mention it in this post and it suddenly had no problems... I think I have a gremlin. That would be a bit easier to handle mentally and emotionally than finding out I've done something horribly stupid.
I don't know if you're able to help, but your last post was near dead-perfect on-the-money so I figure you'll probably have some idea where I went wrong, and your help is appreciated!!
#176712 - mymateo - Fri Sep 16, 2011 6:48 am
D'oh, never mind for now... I've found the culprit for my current predicament, and yes it solved the counting of the updates issue as well. Man I feel stupid... still, I suppose I could just delete my last post...
Anyways, for those who are curious I was calling the wrong... I dunno, what term would you use, parent?... of get_Updates();. I used uResult (which, among several other interfaces, has get_Updates();) and no more crashey, and lots of countey!
Maybe I should stop coding past my bedtime... sleep is a coder's friend, though rarely a companion.