ورود

View Full Version : سوال: چگونه می توان یک برنامه با پارامترهای ورودی ساخت ؟



barnameh08
شنبه 18 دی 1389, 11:18 صبح
سلام

من قصد دارم تو محیط VC++ یک برنامه ویندوزی بنویسم که با پارامترهای ورودی اجرا بشه به عنوان مثال :

در یک bat فایل نوشته شده باشه
test.exe 1 amir

یعنی با کلیک روی exe اجرا نشه مثل بالا دو پارامتر بگیره

میشه راهنماییم کنین ؟

mehdi.mousavi
شنبه 18 دی 1389, 11:38 صبح
سلام من قصد دارم تو محیط VC++ یک برنامه ویندوزی بنویسم که با پارامترهای ورودی اجرا بشه میشه راهنماییم کنین ؟

سلام.
برنامه شما یک تابع WinMain داره که Prototype اش اینه:


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

پارامتر، lpCmdLine حاوی Argument هایی هستش که به برنامه شما هنگام اجرا، پاس میشه. کافیه تا این string رو Parse کنید و اگر اونی نبود که مد نظر شماست، از درون WinMain عدد -1 رو برگردونید. (یا هر عددی غیر از صفر، که نشون بده برنامه با اشکال مواجه شده).

اگر هم برنامه شما از MFC Framework استفاده میکنه، این مقاله (http://www.codeguru.com/forum/showthread.php?t=386406) به شما روش استفاده از کلاس CCommandLineInfo و متود ParseCommandLine رو نشون میده.

موفق باشید.

barnameh08
شنبه 18 دی 1389, 12:31 عصر
ممنون

من از winmain استفاده کردم می تونم پارامتر ها رو دریافت کنم اما هر مقداری برای خروجی می فرستم برنامه بسته میشه

mehdi.mousavi
شنبه 18 دی 1389, 12:36 عصر
من از winmain استفاده کردم می تونم پارامتر ها رو دریافت کنم اما هر مقداری برای خروجی می فرستم برنامه بسته میشه

سلام.
متوجه منظورتون نمیشم، میشه لطفا تابع WinMain خودتون رو اینجا قرار بدید تا ببینم جریان چیه؟ منظورتون از "هر مقداری برای خروجی میفرستم" چیه؟ ببینید. اگر Parameter ها اونی نیستن که شما انتظار دارید، مثلا -1 return کنید. در غیر اینصورت، اجازه بدید برنامه کارش رو انجام بده (بر اساس پارامترهایی که گرفته اید و Parse کرده اید)، سپس در انتهای کار، عدد 0 رو return کنید.

موفق باشید.

barnameh08
شنبه 18 دی 1389, 12:45 عصر
من این کد رو بالای کلاس winapp خودم قرار دادم

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
AfxMessageBox(lpCmdLine);
return 0;
}

پارامترهای ورودی رو برام چاپ می کنه اما بعدش برنامه بسته میشه

mehdi.mousavi
شنبه 18 دی 1389, 13:13 عصر
من این کد رو بالای کلاس winapp خودم قرار دادم پارامترهای ورودی رو برام چاپ می کنه اما بعدش برنامه بسته میشه
آهان، پس برنامه شما MFC هستش. (سوال: یعنی شما تابع WinMain رو بالای کلاسی که از CWinApp مشتق شده تعریف کرده اید؟؟؟ اگر اینطوره، خوب این تابع هرگز Call نمیشه!).
تو برنامه های MFC، باید این چک کردن رو در تابع InitInstance از کلاسی که از CWinApp مشتق شده انجام بدید. گفتم، توی MFC اوضاع متفاوته...

ابتدا یه کلاس درست کنید و اونو از CCommandLineInfo درایو کنید:


class CCommandLineEx: public CCommandLineInfo
{
private:
BOOL m_bOne;

public:
BOOL IsOne() const { return m_bOne; };
CCommandLineEx()
{
m_bOne = FALSE;
}

virtual void ParseParam(const TCHAR* pszParam, BOOL bFlag, BOOL bLast)
{
if(_tcscmp(pszParam, _T("1")) == 0)
{
m_bOne = TRUE;
}
}
};
این کلاسی هستش که من در اون پارامترهای ورودی رو جداگانه نگهداری میکنم و از اون در InitInstance استفاده خواهم کرد. فرض کردم که اگر پارامتر ورودی یک باشه، برنامه اجرا بشه، اگر نه، اجازه نمیدم برنامه اجرا بشه. برای همین، یک متغیر ساختم به اسم m_bOne که نشون میده آیا عدد یک وارد شده یا نه. سپس، توی ParseParam، (که بازای هر پارامتر بطور خودکار Call خواهد شد)، pszParam رو با مقدار "1" مقایسه میکنم. اگر برابر بود، پس m_bOne رو TRUE میکنم. حالا برای اینکه MFC از این کلاس من استفاده کنه، میرم توی تابع InitiInstance و این کد رو می نویسم (همون ابتدای تابع):


BOOL CWinAppApp::InitInstance()
{
CCommandLineEx ci;
ParseCommandLine(ci);
if(!ci.IsOne())
return FALSE;

// 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);
اون 4 خط اول رو من نوشتم، بقیه توسط خود Framework ایجاد شده. اینجا، من با استفاده از ParseCommandLine و یه Instance از کلاسی که پیش تر ساختم، CommandLine فعلی رو بررسی میکنم. اگر عدد یک بود، اجازه میدم برنامه به کارش ادامه بده. در غیر اینصورت FALSE برمیگردونم که باعث میشه برنامه من اجرا نشه.

موفق باشید.

پاورقی: حقیقتا سردرگم شدم. دوباره پاسختون رو خوندم و فکر میکنم برنامه شما MFC نباشه چون گفتید MessageBox مربوطه کار میکنه. خوب اگر کار میکنه، جای MessageBox، پارامترهای ورودی مورد نظرتون رو ببینید همون هایی هستن که میخواهید یا نه. اگر بودن، خوب، برنامه رو اجازه بدید ادامه پیدا کنه و به MessageLoop برسه. اگر نه، -1 رو return کنید. راستش شک کردم که اگر WinMain شما همین دو سه خط هستش، خوب، درسته دیگه. دیگه اهمیتی نداره که پارامترها چی باشن. چه اونی باشن که شما میخواهید، چه اونی نباشن که شما انتظار دارید، در نهایت کدی غیر return 0 وجود نداره که بخواد اجرا بشه. لطفا اگر پاسختون رو هنوز نگرفته اید، کد WinMain خودتون رو بصورت کامل اینجا قرار بدید تا بتونم دقیق براتون توضیح بدم تا مشکلتون رفع بشه.

barnameh08
شنبه 18 دی 1389, 13:46 عصر
برنامه من MFC هستش
اما winmain هم اجرا میشه و پارامترها رو دقیقا همونایی که هستن چاپ می کنه

من چون هنوز از روند کار مطمئن نبودم اصل برنامه رو ننوشتم

پس از اجرا پارامترهایی که ارسال می کنم چاپ میشه ولی برنامه ادامه نمی ده و بسته میشه فرقی نداره خروجی بهش 0 یا 1 و یا -1 بدم

برنامه ای که برام گذاشتین مطمئن هستین کار می کنه

من همین برنامه رو هم نوشتم اما کار نکرد ( پارامترها دریافت نمیشن )

barnameh08
شنبه 18 دی 1389, 13:55 عصر
با تشکر از شما

همون برنامه ای که برام گذاشتین جواب داد

من اول جاشو اشتباه قرار داده بودم

باز هم ممنون

راستی اگه دلیل بسته شدن حالت winmain را متوجه شدید ممنون می شم به من هم خبر بدید

mehdi.mousavi
شنبه 18 دی 1389, 14:06 عصر
راستی اگه دلیل بسته شدن حالت winmain را متوجه شدید ممنون می شم به من هم خبر بدید

واقعیتش من متوجه نمیشم که اون WinMain رو کجای برنامه MFC نوشته اید، و برنامه شما چطوری Compile شده، چون قاعدتا باید خطای LNK2005 رو بده (چون MFC برای خودش WinMain داره (http://www.codeproject.com/KB/cpp/mfc_architecture.aspx) (در appmodul.cpp تعریف شده) و اینطوری Multiple defined symbol خواهید داشت و ...). اگر هم جایی بنویسید که این اتفاق نیفته، اونوقت نمیدونم چطوری اجرا میشه... اگر پروژه شما خالی بوده، ممنون میشم اونو اینجا بذارید تا ببینم چطوری WinMain داره اجرا میشه و کجا اونو نوشته اید...

موفق باشید.

پاورقی: در نهایت، خوشحالم که مشکل رفع شد.

barnameh08
شنبه 18 دی 1389, 14:08 عصر
ببخشید شما گفتید این کلاس به ازای هر پارامتر یک بار صدا زده میشه

قراره برنامه من با 4 پارامتر صدا زده بشه و هر پارامتر را در یک متغییر ذخیره کنم

برای این کار باید چه کنم ( چگونه هر یک از پارامترها را به یک متغیر نسبت بدم وقتی ترتیب را ندونم )


متوجه شدم تمام پارامتر ها رو در یک string قرار بدم و یا تو یک آرایه بریزم و بعد استفاده کنم

با تشکر

barnameh08
شنبه 18 دی 1389, 14:11 عصر
من یک برنامه از نوع دیالوگ ساختم

و این کد برنامه ای هست که از winAPP ارث برده




// Test_CONTROLS.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "Test_CONTROLS.h"
#include "Test_CONTROLSDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
AfxMessageBox(lpCmdLine);
return 0;
}

// CTest_CONTROLSApp
BEGIN_MESSAGE_MAP(CTest_CONTROLSApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()



// CTest_CONTROLSApp construction
CTest_CONTROLSApp::CTest_CONTROLSApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance

}

// The one and only CTest_CONTROLSApp object
CTest_CONTROLSApp theApp;

// CTest_CONTROLSApp initialization
BOOL CTest_CONTROLSApp::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);
CWinApp::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"));
CTest_CONTROLSDlg 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;
}

mehdi.mousavi
شنبه 18 دی 1389, 14:23 عصر
ببخشید شما گفتید این کلاس به ازای هر پارامتر یک بار صدا زده میشه قراره برنامه من با 4 پارامتر صدا زده بشه و هر پارامتر را در یک متغییر ذخیره کنم برای این کار باید چه کنم ( چگونه هر یک از پارامترها را به یک متغیر نسبت بدم وقتی ترتیب را ندونم )

ببینید، متود ParseParam شما 4 بار Call میشه. در نتیجه، هر بار توی یک if میفته، و هر بار یکی از Member Variable های کلاس رو می تونید Set کنید. اینجا رو نگاه کنید:


virtual void ParseParam(const TCHAR* pszParam, BOOL bFlag, BOOL bLast)
{
if(_tcscmp(pszParam, _T("1")) == 0)
{
m_bOne = TRUE;
}
else if (_tcscmp(pszParam, _T("2")) == 0)
{
m_bTwo = TRUE;
}
}


بار اول چون 1 هستش، m_bOne ست میشه. بار دوم، چون پارامتر دوم 2 هستش (برای مثال)، m_bTwo ست میشه و در نهایت، اینطوری، کلیه پارامترهای مورد نظر در Object های مربوطه قرار میگیرن.


من یک برنامه از نوع دیالوگ ساختم و این کد برنامه ای هست که از winAPP ارث برده
جالبه، من الان همین کار رو در VS2010 انجام دادم، اما WinMain ام Call نمیشه... شما از کدوم نسخه MFC استفاده می کنید؟ (شاید تفاوت اینجا باشه).

barnameh08
شنبه 18 دی 1389, 14:39 عصر
من با VS2005 کار میکنم

واقعا از اینکه وقت گذاشتید ممنونم

با تشکر از شما