Making a C++ application "Opened with..." - c++

I'm working on a (C++) program that more or less revolves around renaming files. I would like to make it so that you can select a file, right-mouse click it and select "Open With" and then select my application.
I got the context menu part figured out, I just don't know how to do the C++ part.
In other words, how to make a program (in C++) that can be opened together with a file (so by context menu or directly opening it) and process this file?
Example:
In my Windows, I associate the ".roberto" extension with "C:\Program Files\MyProgram\MyProgram.exe". So if I open a ".roberto" file, a command prompt pops up, only displaying the name of the selected file.
I hope this is clear, I am not sure how to explain this. I also had some trouble with searching on this question, so please forgive me if this has been asked before.
Thanks.

On Windows platform in MFC-based application this is done automatically by framework in InitInstance() method of your application class:
EnableShellOpen();
RegisterShellFileTypes(TRUE);
IMPORTANT: In general this functionality is framework dependent and OS speicific.

I figured it out!
Using the arguments given to main was the clue. The following program prints one line if opened directly, this line is the path of the program itself, and if opened with the 'Open with...' options it also shows the selected file.
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
cout << "Argument count: " << argc << endl << endl;
for (int i = 0; i < argc; i++)
{
cout << argv[i] << endl;
}
cout << endl << endl << endl << endl;
system("pause");
return 0;
}

Related

Only display output for a given time

I just started learning c++ and am using codeblocks. I'm just wondering if there was a way to set my output to display for only a certain amount of time.
For example, I have the code
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world!" << endl;
cout << "You need to learn C++!" << endl;
return 0;
}
Now when I hit build and run, it displays the code and says "Press any key to continue". I want to know if there is a way I can set a timer for that display to go away instead of pressing a key.
Thank you!
Closing the window is not the responsibility of the program to do, it's the user responsibility. Anyway, you could stop the program for the time you want using for stopping the program and for measuring the time you want it to stop. If you double click the .exe file generated after compilation it will automatically close after execution, otherwise you will have to close the window by yourself.
More information here, about the std::thread method: http://www.cplusplus.com/reference/thread/this_thread/sleep_for/
And here about the chrono library:https://en.cppreference.com/w/cpp/chrono/duration
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int main(){
cout << "Hello world!" << endl;
cout << "You need to learn C++!" << endl;
this_thread::sleep_for (chrono::seconds(3));
cout<<"Program finished!";
return 0;
}
You could also use chrono::miliseconds or chrono::minutes or chrono::hours
There may also be a platform dependent library for closing the window . You could have one for windows, another for linux, but anyway you shouldn't be worrying about that as a beginner.

Issues with C++ command-line arguments on Windows

I'm somehow having issues parsing command-line arguments on Windows in C++.
I tried using this
int main(int argc, char **argv)
{
std::cout << "Command-line argument count: " << argc << " \n";
std::cout << "Arguments:\n";
for (int i = 0; i < argc; i++)
std::cout << " argv[" << i << "] "
<< argv[i] << "\n";
return 0;
}
as well as this
int main(int argc, char *argv[])
{
std::cout << "Command-line argument count: " << argc << " \n";
std::cout << "Arguments:\n";
for (int i = 0; i < argc; i++)
std::cout << " argv[" << i << "] "
<< argv[i] << "\n";
return 0;
}
The variables argc and argv seem to be somehow uninitialized.
That's what launching the program returns to me:
Z:\Dev\ProcessSuspender\Debug>ProcessSuspender a
Command-line argument count: 2130558976
Arguments:
argv[0]
argv[1] ╠ÉÉÉÉÉj↑h╚♂YwÞØ÷■ âe³
argv[2]
(crash following)
I compiled it with MSVC12 using the /SUBSYSTEM:CONSOLE linker option.
What could be the cause of this issue?
I've manually set the entry point to main. Whether I use the default project setting (_tmain) or not, the issue persists.
In general, you should not do that unless you know the consequences. The typical values of the entry point (/ENTRY) should be either:
[w]mainCRTStartup, which calls [w]main, or
[w]WinMainCRTStartup, which calls [w]WinMain, or
_DllMainCRTStartup, which calls DllMain.
Why is this needed? Well, the …CRTStartup-family of functions do a couple crucial things, including the initialization of:
the C runtime (CRT),
any global variables, and
the arguments argc and argv, as you've accidentally found out.
So for a typical program you probably want it to do its job. In the Linux world, there is an equivalent function called _start that is needed to do the same initialization tasks as well, which can be overridden with -e while linking.
The confusion here probably stems from difference in ambiguous meaning of the word "entry point": there is the meaning of "apparent entry point" from the perspective of the language (which is main and its ilk), and the meaning of the "true entry point" from the perspective of the language implementation (which is …CRTStartup or _start).
Note that using the …CRTStartup functions is not absolutely essential, as you can certainly write a program that avoids using them. It does come with a cost, however:
you can't use the C runtime, so you can't use most of the standard library,
you need to manually initialize any global variables, and
you need to manually obtain argc and argv using the Windows API (GetCommandLineW and CommandLineToArgvW).
Some do this to avoid dependency on the CRT, or to minimize the executable size.
I tried your project on VS 2012 and it is working smoothly.
I added a getchar(); command as below:
#include <iostream>
int main(int argc, char *argv[])
{
std::cout << "Command-line argument count: " << argc << " \n";
std::cout << "Arguments:\n";
for (int i = 0; i < argc; i++)
std::cout << " argv[" << i << "] "
<< argv[i] << "\n";
getchar();
return 0;
}
so that i could see the output.
Right-click on Project -> Properties -> debugging -> Command
Arguments.
This was empty in my project and i added the character a to simulate your problem.
Here is the output i am getting:
Right click on the project -> Debug -> Start new Instance -> would you
like to build it -> yes
Output:
Command-line argument count: 2
Arguments:
argv[0] <my macines path>\helpingStack1.exe
argv[1] a
Please check this again. I hope this helps.
1) I am suspecting that your binaries are not up to date when you run this script so please do a clean build and verify that you are indeed running the same exe as the one you are building. Please check the configuration - Debug/Release.
2) go to the folder where you have created the project and righclick on the project folder, and change property -> ensure read only is not checked in the check box.
Obviously, Something is wrong with the IDE or project or maybe anything else's setup on your system only.
The code is perfect.
Have you tried directly and independently running your output exe, by executing it through command prompt ??
Run your exe with command prompt by supplying some arbitrary arguments, and check the output.
its worth to check your character set in project properties->General.

How do I get PCRE to work correctly with Code::blocks?

I am facing some problems while working with PCRE in Code::blocks. I have downloaded PCRE from here. And did all the steps mentioned here. However I am getting a pcr3.dll missing error during execution.
The program can't start because pcre3.dll is missing from your
computer. Try reinstalling the program to fix this problem.
My code:
#include <iostream>
#include <regex.h>
using namespace std;
int main(){
regex_t reg;
string pattern = "[^tpr]{2,}";
string str = "topcoder";
regmatch_t matches[1];
regcomp(&reg,pattern.c_str(),REG_EXTENDED|REG_ICASE);
if (regexec(&reg,str.c_str(),1,matches,0)==0) {
cout << "Match " ;
cout << str.substr(matches[0].rm_so,matches[0].rm_eo-matches[0].rm_so) ;
cout << " found starting at: " ;
cout << matches[0].rm_so ;
cout << " and ending at " ;
cout << matches[0].rm_eo ;
cout << endl;
} else {
cout << "Match not found.";
cout << endl;
}
regfree(&reg);
return 0;
}
I am not sure how to fix this, any ideas?
PS: Above mentioned code is taken from this tutorial.
Copy the DLL to the same directory as the executable that you are running. If that works, you didn't install the DLL correctly or at least not in a way that it can be found by the programs in general. Check out the documentation of the DLL Search Order to get an idea how else you can make the system find the DLL. In particular, you need to know that there is a linker and a loader (aka dynamic/runtime linker/loader), but only one of them is configured inside CodeBlocks!

Get ID from MIDI devices in C++

I'm a musician and a programmer and would like to create my own program to make music.
I'll start with a console application in C++ before I make a GUI.
I'm quiet new to C/C++ and know how to make a basic console application and have read about the Win32 API.
I was looking into MSDN for multimedia in Win32 applications and I found a lot of functions for MIDI: http://msdn.microsoft.com/en-us/library/dd798495(VS.85).aspx
I can receive how many MIDI devices are plugged in this way:
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
cout << midiInGetNumDevs();
cout << " MIDI devices connected" << endl;
return 0;
}
But now i want to find out how these devices are called, with the midiInGetID function I think and a while loop. Can somebody help me with this? The function requires a HMIDIIN parameter and I don't know how I can get one since almost all the MIDI functions use this parameter.
I know this is not the most obvious topic but it would be great if someone could help me.
Thanks :)
To get information, you loop calling midiInGetDevCaps, with a first parameter varying from 0 included to the result of midiInGetNumDevs excluded. Each call fills a MIDIINCAPS struct (you pass a pointer to the struct when you call the function) with information about the Nth device. To open a device, and fill the HMIDIIN needed for other calls, you call midiInOpen with the device number (again, 0 to N-1 included) as the second parameter.
The same concept applies to output devices, except that the names have Out instead of In (and for the structures OUT instead of IN).
Ok I figured it out. I didn't know midiInGetDevCaps requires a call to the specific properties of it to return the device name.
Here is my code:
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
unsigned int devCount = midiInGetNumDevs();
cout << devCount << " MIDI devices connected:" << endl;
MIDIINCAPS inputCapabilities;
for (unsigned int i = 0; i < devCount; i++) {
midiInGetDevCaps(i, &inputCapabilities, sizeof(inputCapabilities));
cout << "[" << i << "] " << inputCapabilities.szPname << endl;
}
}
And thanks for your help!

Why does ofstream sometimes create files but can't write to them?

I'm trying to use the ofstream class to write some stuff to a file, but all that happens is that the file gets created, and then nothing. I have some simply code here:
#include <iostream>
#include <fstream>
#include <cstring>
#include <cerrno>
#include <time.h>
using namespace std;
int main(int argc, char* argv[])
{
ofstream file;
file.open("test.txt");
if (!file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
for (int i = 0; i < 10; i++) {
file << i << "\t" << time(NULL) << endl;
}
file.flush();
file.close();
return 0;
}
When I create a console application, everything works fine, so I'm afraid this code is not completely representative. However, I am using code like this in a much larger project that - to be honest - I don't fully understand (Neurostim). I'm supposed to write some class that is compiled to a dll which can be loaded by Neurostim.
When the code is run, "test.txt" is created and then "No error!" is printed, as this is apparently the output from strerror. Obviously this is wrong however. The application runs perfectly otherwise, and is not phased by the fact that I'm trying to write to a corrupted stream. It just doesn't do it. It seems to me like there is no problem with permissions, because the file is in fact created.
Does anyone have any ideas what kind of things might cause this odd behavior? (I'm on WinXP Pro SP3 and use Visual C++ 2008 Express Edition)
Thanks!
Just a thought :- in your real code are you re-using your stream object?
If so, you need to ensure that you call clear() on the stream before re-using the object otherwise, if there was a previous error state, it won't work. As I recall, not calling clear() on such a stream would result in an empty file that couldn't be written to, as you describe in your question.
ofstream file;
file.open("test.txt");
Just a nit: you can combine that into a single line. ofstream file("test.txt");
if (file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
Your test is backwards. If file is true, it's open and ready for writing.
Also, I wouldn't count on strerror() working correctly on Windows. Most Windows APIs don't use errno to signal errors. If your failure is happening outside the C/C++ run-time library, this may not tell you anything interesting.
UPDATE Thinking more about this, failing to open a file via fstreams is not guaranteed to set errno. It's possible that errno ends up set on some platforms (espeically if those platforms implement fstream operations with FILE* or file descriptors, or some other library that sets errno) but that is not guaranteed. The official way to check for failure is via exceptions, std::io_state or helper methods on std::fstream (like fail or bad). Unfortunately you can't get as much information out of std::streams as you can from errno.
You've got the if statement wrong. operator void* returns NULL (a.k.a. false) if the file is not writable. It returns non-zero (a.k.a. true) if the file is writeable. So you want:
if (!file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
Or:
if (!file.good()) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}