QUESTION: I need to check what version and is there one of .net framework installed on user's PC. So here is the deal, first I check a registry for a key, and if it is not found I prompt the user in a Message Box that he does not have .net framework installed and then I would run a .net installation which I'd provide. So, I need to display a Message Box without .net, or is there a way to copy some ".dll" (or something :)) with my application. I am relatively new in visual programming.
ANSWER: Hello Branko
You can create an MFC dialog box project to display a message box without dot net. Visual studio will create almost the entire project for you. You can then add some code to accept message text through the command line and you can call the program from your installer. The exit code of the message box program can be used to tell the installer what action the user selected (ok or cancel).
What are you using to write the installer ? If you are using an installation writer (like install shield) it may already have a way of presenting a message box. Sorry I don't know any installation writer programs.
If you have trouble, send me your email in a private question and I'll try sending you the code. What version of visual studio are you using ?
---------- FOLLOW-UP ----------
QUESTION: Thanks a lot for your advice, I will go with MFC Application, actually I do not really know anything about MFC, so can you please explain how does it work in a few sentences. And if I stuck at some point I am glad I can PM you for a code sample. Thanks for a quick response. I am using VS 2008,my app is written in C#, and I can use C++ to make this check. And about installer I am using Smart Install Maker which is great GUI based install maker, it has it's own .net framework checker but it does not work as it should (as I want him to :)).
ANSWER: It might be simpler to add the dot net checking and installation code into the MFC dialog project. Here is a quick way to do it.
Create a dialog based MFC application. Visual studio will create a lot of code for you. It will create a dialog with a static label called IDC_STATIC. You can rename the label to what you like using the properties panel.
It will create a dialog class in a file ending in Dlg.cpp. In that file, in the class OnInitDialog method you can specify the message text. The method will look something like this:
BOOL CMessageBoxDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } }
// You can add code to display the message here
// The code made by visual studio will depend on the options you have chosen when the project was made.
CStatic* label = (CStatic*)GetDlgItem(IDC_STATIC); label->SetWindowText(_T("Your text here"));
// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control }
Another file will contain the applications InitInstance method. It will look like this.
BOOL CMessageBoxApp::InitInstance() { // InitCommonControlsEx() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); // Set this to include all the common control classes you want to use // in your application. InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls);
CWinAppEx::InitInstance();
AfxEnableControlContainer();
// Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need // Change the registry key under which our settings are stored // TODO: You should modify this string to be something appropriate // such as the name of your company or organization SetRegistryKey(_T("Local AppWizard-Generated Applications"));
CMessageBoxDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel }
// Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; }
In the TODO sections you can place the dot net installation code. Add the dot net checking somewhere before dlg.DoModal() and call the DoModal if dot net is not installed. The DoModal causes the dialog to appear.
I hope that helps you out.
---------- FOLLOW-UP ----------
QUESTION: MFC works fine, registry check works fine, but running a file does not. First I used shellexecute but nothing happens, then I used system("file.exe"). It runs my file but the installation of .net I have got first extracts some data in a temporarily folder and then runs the instllation of .net. So system command starts, .net is extracting and then it ends, so the installation does not start. Any other run file commands?
Branko, I usually use CreateProcess to start another program. Below is some sample code I was using to start the MFC project. I am not sure about the problem you are experiencing, but I think you need to synchronize the parent and child processes. You want the parent to pause while the dot net is being extracted and installed. Is that correct? The code below starts a process, then waits for it to exit. When the child exist, the parent reads the exit code, and finally closes handles to the child. In my testing, the child executable was in the same directory as the parent. I suspect that will be the case in your installation program.
const char* GetLastErrorMessage(void) {
static char result[128]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, result, sizeof(result), NULL); return result;
}
int main(int argc, char* argv[]) {
STARTUPINFO startupInfo; memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo);
PROCESS_INFORMATION procInfo; memset(&procInfo, 0, sizeof(procInfo));
if (CreateProcess(NULL, "MessageBox.exe \"Your message\ngoes here\"", NULL, NULL, false, 0, NULL, NULL, &startupInfo, &procInfo) != 0) { while(true) { DWORD exitCode; if (GetExitCodeProcess(procInfo.hProcess, &exitCode) != 0) { if (exitCode != STILL_ACTIVE) { std::cout << "exitCode is " << exitCode << std::endl; break; } else Sleep(500); // keep CPU usage down } else { std::cout << "GetExitCodeProcess failed: " << GetLastErrorMessage() << std::endl; break; } }
CloseHandle(procInfo.hThread); CloseHandle(procInfo.hProcess); } else { std::cout << "CreateProcess failed: " << GetLastErrorMessage() << std::endl; } return 0;
}
Advertisement