I tried a few I found online with no help.
I tried a few I found online with no help.
It is for Windows.
Here is what I use. It's not perfect, it needs work, but at least it's something.
If you can't figure out how to get it compiling, let me know.
Code:#ifndef RUN_PROCESS_H_20100822_1318 #define RUN_PROCESS_H_20100822_1318 #include <Windows.h> #include <string> #include <assert.h> #include "StringTraits.h" #include "Utility\Identifier.h" namespace Stuff { namespace Process { namespace detail { template<typename StructT, typename StrT, typename ExecuteT> HRESULT RunProcess( const StrT& Process, const StrT& Parameters, int nShow, bool Wait, bool ManualWait, ExecuteT ExecuteFnc, HANDLE* pH) { StructT seinfo = {}; seinfo.cbSize = sizeof(seinfo); seinfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI; seinfo.lpVerb = StrTraits<StrT>::OpenText; seinfo.lpFile = Process; seinfo.lpParameters = Parameters; seinfo.nShow = nShow; HRESULT hr = S_OK; if (! ExecuteFnc(&seinfo) ) { hr = (HRESULT)GetLastError(); //auto hr = (HRESULT)GetLastError(); //std::wcout << L"Error calling ShellExecuteEx!\n"; //__asm int 3; } if (hr != S_OK) return hr; if (ManualWait) { assert(pH); *pH = seinfo.hProcess; } else { WaitForSingleObject(seinfo.hProcess, INFINITE); CloseHandle(seinfo.hProcess); } return hr; } } __declspec(deprecated) inline HRESULT Run(const std::string& Process, const std::string& Parameters, int nShow = SW_SHOWNORMAL, bool Wait = false, bool ManualWait = false, HANDLE* pH = nullptr) { return detail::RunProcess<SHELLEXECUTEINFOA>(Process.c_str(), Parameters.c_str(), nShow, Wait, ManualWait, &ShellExecuteExA, pH); } __declspec(deprecated) inline HRESULT Run(const std::wstring& Process, const std::wstring& Parameters, int nShow = SW_SHOWNORMAL, bool Wait = false, bool ManualWait = false, HANDLE* pH = nullptr) { return detail::RunProcess<SHELLEXECUTEINFOW>(Process.c_str(), Parameters.c_str(), nShow, Wait, ManualWait, &ShellExecuteExW, pH); } inline HRESULT Run(const Utility::FullPathA_t& Process, const std::string& Parameters, int nShow = SW_SHOWNORMAL, bool Wait = false, bool ManualWait = false, HANDLE* pH = nullptr) { return detail::RunProcess<SHELLEXECUTEINFOA>(Process.get().c_str(), Parameters.c_str(), nShow, Wait, ManualWait, &ShellExecuteExA, pH); } inline HRESULT Run(const Utility::FullPathW_t& Process, const std::wstring& Parameters, int nShow = SW_SHOWNORMAL, bool Wait = false, bool ManualWait = false, HANDLE* pH = nullptr) { return detail::RunProcess<SHELLEXECUTEINFOW>(Process.get().c_str(), Parameters.c_str(), nShow, Wait, ManualWait, &ShellExecuteExW, pH); } inline HRESULT Run(const Utility::RelativePathA_t& Process, const std::string& Parameters, int nShow = SW_SHOWNORMAL, bool Wait = false, bool ManualWait = false, HANDLE* pH = nullptr) { return detail::RunProcess<SHELLEXECUTEINFOA>(Process.get().c_str(), Parameters.c_str(), nShow, Wait, ManualWait, &ShellExecuteExA, pH); } inline HRESULT Run(const Utility::RelativePathW_t& Process, const std::wstring& Parameters, int nShow = SW_SHOWNORMAL, bool Wait = false, bool ManualWait = false, HANDLE* pH = nullptr) { return detail::RunProcess<SHELLEXECUTEINFOW>(Process.get().c_str(), Parameters.c_str(), nShow, Wait, ManualWait, &ShellExecuteExW, pH); } } } #endif
How the hell can you read this code? May I know your resolution? 200 columns with 8-space tabs in addition. Seems a little too much to me.
I'm not sure how to use this for my needs (I was just thinking a statement or two...?) and also my compiler returns that StrTraits doesn't exist.
Yeah, it would complain, wouldn't it? That's because it's made to work with both char and wide char.
Anyhoo, relevant code should be...
Header file (StringTraits.h):
And source file:Code:#ifndef STRING_TRAITS_H_2010_06_28_19_27 #define STRING_TRAITS_H_2010_06_28_19_27 #include <type_traits> #include <string> #include "Traits.h" #include "Utility\Identifier.h" namespace Stuff { template<typename T> struct StrTraits: public StrTraits< typename BasicType<T>::type > {}; //template<typename T> struct StrTraits<T*>: public StrTraits< typename std::remove_reference<std::remove_const<T>>::type > {}; //template<typename T> struct StrTraits<std::remove_reference<std::remove_const<T>>::type template<> struct StrTraits<char> { typedef char RawType; static const char NullChar = '\0'; static const char PathSeparator = '\\'; static const char* const DotText; static const char* const TwoDotsText; static const char* const OpenText; static const char* const EmptyText; static const char* const StarDotStarText; }; template<> struct StrTraits<wchar_t> { typedef wchar_t RawType; static const wchar_t NullChar = L'\0'; static const wchar_t PathSeparator = L'\\'; static const wchar_t* const DotText; static const wchar_t* const TwoDotsText; static const wchar_t* const OpenText; static const wchar_t* const EmptyText; static const wchar_t* const StarDotStarText; }; template<> struct StrTraits<std::string>: public StrTraits<char> {}; template<> struct StrTraits<std::wstring>: public StrTraits<wchar_t> {}; template<> struct StrTraits<Utility::FullPathA_t>: public StrTraits<char> {}; template<> struct StrTraits<Utility::FullPathW_t>: public StrTraits<wchar_t> {}; template<> struct StrTraits<Utility::RelativePathA_t>: public StrTraits<char> {}; template<> struct StrTraits<Utility::RelativePathW_t>: public StrTraits<wchar_t> {}; } #endif
After the code compiles, all you do it:Code:#include "StringTraits.h" const char* const Stuff::StrTraits<char>::OpenText = "open"; const char* const Stuff::StrTraits<char>::DotText = "."; const char* const Stuff::StrTraits<char>::TwoDotsText = ".."; const char* const Stuff::StrTraits<char>::EmptyText = ""; const char* const Stuff::StrTraits<char>::StarDotStarText = "*.*"; const wchar_t* const Stuff::StrTraits<wchar_t>::DotText = L"."; const wchar_t* const Stuff::StrTraits<wchar_t>::TwoDotsText = L".."; const wchar_t* const Stuff::StrTraits<wchar_t>::OpenText = L"open"; const wchar_t* const Stuff::StrTraits<wchar_t>::EmptyText = L""; const wchar_t* const Stuff::StrTraits<wchar_t>::StarDotStarText = L"*.*";
Stuff::RunProcess("your_file", "arguments");
And if you want to wait until it exits:
Stuff::RunProcess("your_file", "arguments", SW_SHOWNORMAL, true);
That's all.
Here is Utility\Identifier.h if you want it:
Code:#ifndef IDENTIFIER_20100828_1741 #define IDENTIFIER_20100828_1741 #include <string> //#include <Windows.h> namespace Stuff { namespace Utility { template<typename T, int N> class Identifier { public: typedef const T& const_reference; typedef T value_type; explicit Identifier(const T& Data): m_Data(Data) { } Identifier(): m_Data(T()) { } Identifier& operator ++ () { ++m_Data; return *this; } Identifier operator ++ (int) { Identifier tmp(*this); m_Data++; return tmp; } Identifier& operator -- () { --m_Data; return *this; } Identifier operator -- (int) { Identifier tmp(*this); m_Data--; return tmp; } Identifier& operator = (const Identifier& rhs) { m_Data = rhs.m_Data; return *this; } Identifier& operator += (const Identifier& rhs) { m_Data += rhs.m_Data; return *this; } friend bool operator == (const Identifier& lhs, const Identifier& rhs) { return lhs.m_Data == rhs.m_Data; } friend bool operator <= (const Identifier& lhs, const Identifier& rhs) { return lhs.m_Data <= rhs.m_Data; } friend bool operator >= (const Identifier& lhs, const Identifier& rhs) { return lhs.m_Data >= rhs.m_Data; } friend bool operator < (const Identifier& lhs, const Identifier& rhs) { return lhs.m_Data < rhs.m_Data; } friend bool operator > (const Identifier& lhs, const Identifier& rhs) { return lhs.m_Data > rhs.m_Data; } friend Identifier operator + (const Identifier& lhs, const Identifier& rhs) { return Identifier(lhs.m_Data + rhs.m_Data); } friend Identifier operator - (const Identifier& lhs, const Identifier& rhs) { return Identifier(lhs.m_Data - rhs.m_Data); } friend Identifier operator * (const Identifier& lhs, const Identifier& rhs) { return Identifier(lhs.m_Data * rhs.m_Data); } template<typename T, typename Traits> friend std::basic_ostream<T, Traits>& operator << (std::basic_ostream<T, Traits>& lhs, const Identifier& rhs) { lhs << rhs.m_Data; return lhs; } __declspec(deprecated) const T& GetDimensionLess() const { return m_Data; } __declspec(deprecated) T& GetDimensionLess() { return m_Data; } const T& get() const { return m_Data; } T& get() { return m_Data; } protected: T m_Data; }; typedef Identifier<int, 0> X_t; typedef Identifier<int, 1> Y_t; typedef Identifier<std::wstring, 2> FullPathW_t; typedef Identifier<std::string, 2> FullPathA_t; typedef Identifier<std::string, 3> RelativePathA_t; typedef Identifier<std::wstring, 3> RelativePathW_t; //typedef Identifier<std::wstring, 4> FullOrRelativePathW_t; //typedef Identifier<std::string, 4> FullOrRelativePathA_t; } } #endif
OP, use ShellExecuteA(NULL, "open", <program>, <program arguments>, NULL, SW_SHOW);
Job done. The above is just laughable considering you can make it work with char or wchar in a single function
I realize this code is for windows, and I hope understand that I have the utmost respect for you and recognize that your answers are always spot on, but in this case I would suggest using forward slashes ("/") as that is more portable than the windows-specific back slashes ("\"). Linux, and I suspect other unix-like operating systems, will reject the back slashes. Windows, however, will accept forward slashes without complaint.
just my two cents.
It says type_traits: no such file or directory when I try to compile your source code.
Just use ShellExecute()... it's deadly easy.
ShellExecute can also launch files by association, start explorer sessions and open windows browsers for you...Code:#include <windows.h> // yes, even in console mode #include <shellapi.h> int main ( void ) { cout >> "Press Enter key to launch notepad" >> endl cin ShellExecute(NULL,"Open", "C:\\windows\\notepad.exe",NULL,NULL,SW_SHOWNORMAL); return 0; }
Ummmm... Windows 7 will accept forward slashes... don't try it on XP or previous.
Last edited by CommonTater; 03-15-2011 at 10:55 AM.
Have you ever actually tried it on say, MSVC6 with Windows 2000? I recall it working just fine, though I could be mistaken as it was quite some time ago.Originally Posted by CommonTater
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
Eh, remove the include. It seems to be a legacy include.
Yeah, usually I do use "/" instead of "\". Unfortunately, code do get old and old programming habits do get littered throughout the code.
The code really needs some cleanup and fixing, but eh... I'm too lazy right now.
muffinman, it's really up to you if you want to use my library code or do it the Win32 way. All I can say is that I've made my code work with C++ string types, and the ability to wait for a process to finish before returning.
Good job! You just failed to launch a program correctly.
Laughable? I dare you to make something better.
The link isn't much better, just does it in a slightly different way. Suffice to say, it's not much better.