在win10中双击运行linux程序的实现,VC++9代码

#pragma once

class CLXConsole
{
public:
    CLXConsole(void);
    virtual ~CLXConsole(void);
    
public:
    
    //创建控制台窗口
    BOOL	CreateConsole();
    
    //读输入
    BOOL	Read(CString &inStr);
    
    //任意键
    char	ReadChar();
    
    BOOL	Write(const LPCSTR szFormat,...);
    
    BOOL	Loop();

    BOOL	ExecCmd(LPCSTR szCMD);
    
    //运行
    BOOL	LXLoader(int argc,char* argv[]);

    //运行原始程序
    BOOL	RunDefault(int argc,char* argv[]);
    
    //判断是否为ELF文件
    BOOL	IsELF(CString &filePath);
    
    //判断是否安装到系统
    BOOL	IsInstall();

    //安装
    BOOL	InstallLoader();

    //卸载
    BOOL	UninstallLoader();

    //取得默认路径
    CString	GetDefaultExePath();

    //取得当前程序路径
    CString GetCurrentPath();
    
    BOOL	OpenKey(CRegKey &key);

    CString QueryKey(LPCSTR lpszKeyName);
    BOOL	SetKey(LPCSTR lpszKeyName,LPCSTR lpszValue,BOOL bExString=FALSE);
    BOOL	DeleteKey(LPCSTR lpszKeyName);

    static	BOOL		WriteFile(LPCSTR lpszFile,LPCSTR lpszString);
private:
    
    static	BOOL WINAPI HandlerRoutine(DWORD dwCtrlType);

    BOOL	m_bFreeConsole;
    char	*m_lpBuffer;
    #define MAX_IN_BUFFER 8192

    HANDLE	m_hOutput;
    HANDLE	m_hInput;
};
#include "StdAfx.h"
#include "LXConsole.h"

CLXConsole::CLXConsole(void)
:m_bFreeConsole(FALSE)
{
    m_lpBuffer=new char[MAX_IN_BUFFER];
    RtlZeroMemory(m_lpBuffer,MAX_IN_BUFFER);
}

CLXConsole::~CLXConsole(void)
{
    if (m_bFreeConsole)
    {
        SetConsoleCtrlHandler(HandlerRoutine,FALSE);
        FreeConsole();
    }
    delete m_lpBuffer;
}

CString GetLastErrorString( DWORD dwErrCode/*=NULL*/ )
{
    DWORD dwSrcCode=0;
    CString strResult(__T(""));TCHAR* buffer;
    if(!dwErrCode)
    {
        dwErrCode=::GetLastError();
        dwSrcCode=dwErrCode;
    }

    ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,dwErrCode,0,( LPTSTR )&buffer,0,NULL);
    if ((int)dwErrCode>=0)
    {
        strResult.Format(__T("(%d):%s"),dwErrCode,buffer);
    }else{
        strResult.Format(__T("(0x%08X):%s"),dwErrCode,buffer);
    }
    strResult.Replace(__T("\r\n"),_T(" "));
    LocalFree( buffer );

    if (dwSrcCode) ::SetLastError(dwSrcCode);

    return strResult;
}

BOOL WINAPI CLXConsole::HandlerRoutine(DWORD dwCtrlType)
{
    switch (dwCtrlType)
    {
    case CTRL_C_EVENT:
        break;  
    case CTRL_BREAK_EVENT:
        break;
    case CTRL_CLOSE_EVENT:
        ::TerminateProcess(::GetCurrentProcess(),0);
        break;  
    case CTRL_LOGOFF_EVENT:
        break;  
    case CTRL_SHUTDOWN_EVENT:
        break;
    }
    return TRUE;
}

BOOL CLXConsole::CreateConsole()
{
    ASSERT(m_bFreeConsole==FALSE);
    m_bFreeConsole=AllocConsole();
    if (m_bFreeConsole)
    {
        m_hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
        m_hInput=GetStdHandle(STD_INPUT_HANDLE);
        if (!m_hOutput 
            || !m_hInput
            || !SetConsoleCtrlHandler(HandlerRoutine,TRUE))
        {
            CloseHandle(m_hOutput);
            CloseHandle(m_hInput);
            FreeConsole();
            m_bFreeConsole=FALSE;
        }
    }
        
    return m_bFreeConsole;
}

BOOL CLXConsole::Read(CString &inStr)
{
    inStr.Empty();
    
    TCHAR szBuffer[1024]={0};
    DWORD	dwReadBuffer=0;
    BOOL bResult=ReadConsole(m_hInput,szBuffer,sizeof(szBuffer)-1,&dwReadBuffer,NULL);
    
    if (bResult)
    {
        inStr=szBuffer;
    }

    return bResult;
}

char CLXConsole::ReadChar()
{
    TCHAR szBuffer[2]={0};
    DWORD	dwReadBuffer=0;
    BOOL bResult=ReadConsole(m_hInput,szBuffer,sizeof(szBuffer)-1,&dwReadBuffer,NULL);
    if (bResult)
    {
        return szBuffer[0];
    }
    return 0;
}

BOOL CLXConsole::Write(const LPCSTR szFormat,...)
{
    CString   strMessage;
    va_list   arglist;
    va_start(arglist, szFormat);
    strMessage.FormatV(szFormat,arglist);
    va_end(arglist);
    
    DWORD dwWrite=0;
    BOOL bResult=WriteConsole(m_hOutput,(LPCSTR)strMessage,strMessage.GetLength(),&dwWrite,NULL);
    
    return bResult;
}

BOOL CLXConsole::Loop()
{
    CString cmdStr;
    
    do 
    {
        if (!Read(cmdStr))
        {
            break;
        }
        system(cmdStr);
    } while (TRUE);
    
    return TRUE;
}

BOOL CLXConsole::ExecCmd(LPCSTR szCMD)
{
    return system(szCMD)==0;
}

BOOL CLXConsole::LXLoader(int argc,char* argv[])
{
    CString fileFullPath;	//文件路径
    CString filePath;
    CString fileExt;	//扩展名
    CString fileName;	//文件名
    
    fileFullPath=argv[0];
        
    int nEndChar=fileFullPath.ReverseFind('\\');
    if(nEndChar==-1)
    {
        //路径中没有\\ 退出
        return FALSE;
    }
    
    filePath=fileFullPath.Left(nEndChar+1);
    
    fileName=fileFullPath.Right(fileFullPath.GetLength()-nEndChar-1);
    nEndChar=fileName.ReverseFind('.');
    if (nEndChar!=-1)
    {
        fileExt=fileName.Right(fileName.GetLength()-nEndChar-1);
    }
    
    //暂时只处理没有扩展名的
    if (!fileExt.IsEmpty())
    {
        return FALSE;
    }
    
    //判断是否为ELF执行文件
    if (!IsELF(fileFullPath))
    {
        return FALSE;
    }
    
    BOOL bCurrDir=TRUE;
    
    CString shScript;
    shScript.Format("./%s",fileName);
    
    CString shName;
    shName.Format("LXLoader_%d.sh",::GetTickCount());
    
    CString shFile;
    shFile.Format("%s%s",filePath,shName);
    
    if(!WriteFile(shFile,shScript))
    {
        CString errMsg;
        errMsg.Format("无法写入此文件:\r\n%s",shFile);
        AfxMessageBox(errMsg);
        return FALSE;
    }
    
    CFileStatus rStatus;
    CFile::GetStatus(shFile,rStatus);//获得文件的属性设置
    rStatus.m_attribute=rStatus.m_attribute | 0x2 | 0x4 ;
    CFile::SetStatus(shFile, rStatus );
    
    //防止程序退出造成的垃圾文件
    ::MoveFileExA(shFile,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
    
    if (!CreateConsole())
    {
        return FALSE;
    }
    
    CString cmdStr;
    cmdStr.Format("bash %s",shName);
    
    CString titleStr;
    titleStr.Format("Linux:%s",fileFullPath);
    SetConsoleTitle(titleStr);
    
    ExecCmd(cmdStr);
    
    ::DeleteFileA(shFile);
    
    //ExecCmd("pause");
    
    ExecCmd("bash");
    
    return TRUE;
}

BOOL CLXConsole::RunDefault(int argc,char* argv[])
{
    CString defExe(QueryKey("lx_old"));
    
    if (defExe.IsEmpty()) return FALSE;
    
    defExe.Replace("%1",argv[0]);
    
    //::ShellExecute(NULL,NULL,defExe,NULL,NULL,SW_SHOWDEFAULT);
    //::WinExec(defExe,SW_SHOWDEFAULT);
    
    CString curDir;
    DWORD dwSize=::GetCurrentDirectory(1024,curDir.GetBuffer(1025));
    curDir.ReleaseBuffer(dwSize);
    
    STARTUPINFO st={0};
    st.cb=sizeof(STARTUPINFO);
    GetStartupInfo(&st);
    
    PROCESS_INFORMATION pi={0};

    DWORD dwFlags=NULL;
    
    defExe="%SystemRoot%\\SysWow64\\OpenWith.exe";

    dwFlags|=CREATE_NEW_CONSOLE;
    dwFlags|=CREATE_DEFAULT_ERROR_MODE;
    
    TCHAR szPath[100] ={0};  
    GetWindowsDirectory( szPath, 100 ) ;  
    
    defExe=szPath;
    defExe+="\\SysWOW64\\OpenWith.exe \"";
    defExe+=argv[0];
    defExe+="\"";

    BOOL bResult=::CreateProcess(NULL,(LPSTR)(LPCSTR)defExe,NULL,NULL,NULL
        ,dwFlags,NULL,
        curDir,&st,&pi);
    //strCommandLine.ReleaseBuffer();
    //c:\\Windows\\SysWOW64\\OpenWith.exe
    //::ShellExecuteA(NULL,"open",NULL,__argv[0],curDir,SW_SHOWDEFAULT);
    
    //AfxMessageBox(GetLastErrorString(0));
    
    return bResult;
}

BOOL CLXConsole::IsELF(CString &filePath)
{
    CFile fileObj;
    if (!fileObj.Open(filePath,CFile::modeRead|CFile::shareDenyNone))
    {
        CString errMsg;
        errMsg.Format("无法读取此文件:\r\n%s",filePath);
        AfxMessageBox(errMsg);
        return FALSE;
    }
    
    char szBuffer[4]={0};
    if (fileObj.GetLength()<4)
    {
        fileObj.Close();
        return FALSE;
    }
    
    if(fileObj.Read(szBuffer,4)!=4)
    {
        CString errMsg;
        errMsg.Format("读取文件数据失败:\r\n%s",filePath);
        AfxMessageBox(errMsg);
        return FALSE;
    }
    fileObj.Close();
    
    if (szBuffer[0]==0x7F
        && szBuffer[1]==0x45
        && szBuffer[2]==0x4c
        && szBuffer[3]==0x46)
    {
        return TRUE;
    }

    return FALSE;
}

BOOL CLXConsole::IsInstall()
{
    CString exePath=GetCurrentPath();
    CString curPath=GetDefaultExePath();
    if (curPath.IsEmpty())
    {
        AfxMessageBox("操作失败,可能不支持此系统\r\n计算机\\HKEY_CLASSES_ROOT\\Unknown\\shell\\openas\\command\\默认值为空");
        ::ExitProcess(1);
    }
    
    exePath.MakeLower();
    curPath.MakeLower();
    if (curPath.Find(exePath)!=-1)
    {
        return TRUE;
    }else{
        if (curPath.Find(" -lxloader")!=-1)
        {
            AfxMessageBox("LXLoader程序路径已改变,需要重新安装!");
        }
        return FALSE;
    }
}

BOOL CLXConsole::InstallLoader()
{
    CString oldExe(QueryKey("lx_old"));
    if (oldExe.IsEmpty())
    {
        oldExe=QueryKey(NULL);
    }

    CString DelegateExecute(QueryKey("DelegateExecute"));
    SetKey("lx_old",oldExe);
    if (!DelegateExecute.IsEmpty())
    {
        SetKey("lx_DelegateExecute",DelegateExecute);
        DeleteKey("DelegateExecute");
    }
    
    CString curExe(GetCurrentPath());
    curExe+="\" \"%1\" -lxloader";
    curExe="\""+curExe;
    SetKey(NULL,curExe,TRUE);
    
    return TRUE;
}

BOOL CLXConsole::UninstallLoader()
{
    CString lx_DelegateExecute(QueryKey("lx_DelegateExecute"));
    CString lx_old(QueryKey("lx_old"));
    
    if (!lx_old.IsEmpty())
    {
        SetKey(NULL,lx_old,TRUE);
        DeleteKey("lx_old");
    }
    
    if (!lx_DelegateExecute.IsEmpty())
    {
        SetKey("DelegateExecute",lx_DelegateExecute);
        DeleteKey("lx_DelegateExecute");
    }
    
    return TRUE;
}

CString CLXConsole::QueryKey(LPCSTR lpszKeyName)
{
    CString msg;
    CRegKey key;
    
    if (!OpenKey(key)) return FALSE;
    LONG lResult=0;
    
    CString valueString;
    DWORD	dwSize=1024;
    lResult=key.QueryStringValue(lpszKeyName,valueString.GetBuffer(1025),&dwSize);
    valueString.ReleaseBuffer(dwSize);
    
    if (lResult==ERROR_INVALID_DATA)
    {
        DWORD	dwType=REG_EXPAND_SZ;
        dwSize=1024;
        lResult=key.QueryValue(lpszKeyName,&dwType,(void*)valueString.GetBuffer(1025),&dwSize);
        valueString.ReleaseBuffer(dwSize);
    }
    
    if(lResult!=ERROR_SUCCESS && lResult!=2)
    {
        msg.Format("查询值失败:\r\nUnknown\\shell\\openas\\command\\%s\r\n%s"
            ,lpszKeyName,GetLastErrorString(lResult));
        AfxMessageBox(msg);
        ::TerminateProcess(GetCurrentProcess(),1);
    }
    
    key.Close();
    return valueString;
}

BOOL CLXConsole::SetKey(LPCSTR lpszKeyName,LPCSTR lpszValue,BOOL bExString)
{
    CString msg;
    CRegKey key;

    if (!OpenKey(key)) return FALSE;
    LONG lResult=0;
    
    lResult=key.SetStringValue(lpszKeyName,lpszValue,bExString?REG_EXPAND_SZ:REG_SZ );
    key.Close();

    if(lResult!=ERROR_SUCCESS)
    {
        msg.Format("修改值失败:\r\nUnknown\\shell\\openas\\command\\%s\r\n%s"
            ,lpszKeyName,GetLastErrorString(lResult));
        AfxMessageBox(msg);
        ::TerminateProcess(GetCurrentProcess(),1);
    }

    return TRUE;
}

BOOL CLXConsole::DeleteKey(LPCSTR lpszKeyName)
{
    CString msg;
    CRegKey key;
    
    if (!OpenKey(key)) return FALSE;
    LONG lResult=0;

    lResult=key.DeleteValue(lpszKeyName);
    if (lResult!=ERROR_SUCCESS)
    {
        msg.Format("删除值失败:\r\nUnknown\\shell\\openas\\command\\%s\r\n%s"
            ,lpszKeyName,GetLastErrorString(lResult));
        AfxMessageBox(msg);
        ::TerminateProcess(GetCurrentProcess(),1);
    }

    key.Close();
    return TRUE;
}

BOOL CLXConsole::OpenKey(CRegKey &key)
{
    CString msg;
    LONG lResult=0;
    lResult=key.Open(HKEY_CLASSES_ROOT,_T("Unknown\\shell\\openas\\command"),KEY_ALL_ACCESS);
    if (lResult!=ERROR_SUCCESS)
    {
        msg.Format("%s\r\nHKEY_CLASSES_ROOT\\Unknown\\shell\\openas\\command"
            ,GetLastErrorString(lResult));
        AfxMessageBox(msg);
        ::TerminateProcess(GetCurrentProcess(),1);
    }
    return TRUE;
}

CString CLXConsole::GetDefaultExePath()
{
    return QueryKey(NULL);
}

CString CLXConsole::GetCurrentPath()
{
    CString exePath;
    DWORD dwSize=::GetModuleFileName(NULL,exePath.GetBuffer(1025),1024);
    exePath.ReleaseBuffer(dwSize);
    return exePath;
}

BOOL CLXConsole::WriteFile(LPCSTR lpszFile,LPCSTR lpszString)
{
    CFile file;
    if (!file.Open(lpszFile,CFile::modeWrite|CFile::modeCreate))
    {
        return FALSE;
    }
    
    file.Write(lpszString,(UINT)strlen(lpszString));

    return TRUE;
}
BOOL CLXLoaderApp::InitInstance()
{
    CWinAppEx::InitInstance();
    
    SetRegistryKey(_T("LXLoader"));
    
    if (__argc==1)
    {
        CLXLoaderDlg dlg;
        m_pMainWnd = &dlg;
        INT_PTR nResponse = dlg.DoModal();
    }else{
        CLXConsole	console;
        if(!console.LXLoader(__argc-1,&__argv[1]))
        {
            console.RunDefault(__argc-1,&__argv[1]);
        }
        return TRUE;
    }
        
    return FALSE;
}

 

目前只能打开路径不在linux安装路径下的文件

下载:LXLoader

仅支持win10,且已安装linux子系统

发表评论

电子邮件地址不会被公开。