2016-06-08 116 views
-1

我們正在使用解析一系列計算機生成的郵件的解析器程序(我無法訪問它),但需要一些幫助來決定特定的操作。因此,員工可以使用主題行來獲取其他命令。由於每天有超過500封電子郵件供我們使用,並且所有的命令都看起來類似於:Ba,Vi;#TD*; x0003,所以不可能手動編寫它們。於是我編寫了一個小型的C#腳本,創建了一個可以完成90%工作的Autohotkey腳本。理論上。它的工作原理,但只要我不使用任何特殊字符,如, : & % etc使Autohotkey忽略字符串中的任何特殊字符

我想:

clipboard := Ba{,}Vi{;}{#}TD{*}{;} x0003 
clipboard := "Ba,Vi;#TD*; x0003" 
clipboard := Ba',Vi';'#TD'*'; x0003 
clipboard := {raw} Ba,Vi;#TD*; x0003 
(plus some others that I probably forgot here) 


下面是帶有註釋的整個AHK腳本。你開始它,而在Outlook中在選擇郵件:

;Win+z -> start script 
#z:: 

;Currently only one iteration 
loop,1 
{ 

    ;CTRL+F to forward selected mail, 
    ;which then automatically selects the "To:" line 
    Send, {CTRLDOWN}f{CTRUP} 
    Sleep, 500 
    Send, [email protected] 
    Sleep, 500 

    ;Initialize GUI 
    Gui, +AlwaysOnTop 
    Gui, Font, S5, Verdana, bold 
    Gui, Add, Text,, SCANNING-BOOSTER: 
    Gui, Color, F4A460 

    ;Example for the C# generated buttons below (they all do the same thing): 
    ;Clicking the Button "Google" will run the following script 
    ;Start: 
    ;clipboard := www.Google.com 
    ;return 
    ;This is the part where AHK fails because instead 
    ;of www.Google.com I have codes like "Ba,Vi;#TD*; x0003" which crash AHK 

    Gui,add,Button,gLabel,Google 
    Gui,add,Button, ...... 
    Gui,add,Button, ...... 
    Gui,add,Button, ...... 
    Gui,add,Button, ...... 
    Gui,add,Button, ...... 
    ..... (around 60 more auto-generated buttons) 
    Gui,show 
    Return 
    Label: 
    ;run the script that has the same name as the Button 
    ;in this case it would be Google.ahk 
    Run, % A_GuiControl ".ahk" 

    GuiClose: 
      Gui, Hide 

    Sleep, 1000 


    ;after the user has pressed a button and the according code 
    ;has been copied to the clipboard, the GUI closes, the 
    ;mail window becomes active again and we can continue to paste 
    ;the code into the subject line 

    ;Go to subject line 
    Send, {ALTDOWN}r{ALTUP} 
    Sleep, 500 

    ;CTRL+a 
    Send, {CTRLDOWN}a{CTRUP} 
    Sleep, 500 

    ;Write text from your clipboard to the subject line 
    Send, %clipboard% 
    Sleep, 500 

    return 
} 
+1

你的腳本是做什麼的?它應該做什麼?請提供您的代碼並指出哪些方面無效。無論如何,請查看[#EscapeChar](https://autohotkey.com/docs/commands/_EscapeChar.htm)並轉義每個具有特殊含義的字符。 – MCL

+0

整個腳本已添加註釋。這顯然不是最終的,但我需要在剪輯板部分能夠繼續完成之前完成剪貼板部分。轉義字符的問題是,我不完全知道將使用哪些字符,因爲將來會添加和刪除參數。 –

+0

問題是什麼?你有錯誤或不需要的行爲?請解釋什麼解釋什麼不起作用以及如何工作。 – MCL

回答

0

顯然,這是目前無法將(或多或少)隨機字符串複製到AutoHotkey的剪貼板,然後將其粘貼在其他地方沒有收到這麼多的錯誤值得追求它。除了用C#編寫所有東西外,我別無選擇。以下是我做的:

首先,啓動一個新的控制檯應用程序,然後將其更改爲Windows應用程序
How to change a console application to a windows form application?
這是爲了使程序完全對用戶不可見的最簡單方法。

接下來,我們需要一個關鍵的監聽器。這是我用的一個:
https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/
我會建議你把它放在一個新班級。無論如何,該代碼需要稍微改變,因爲它將每次按鍵都打印到控制檯。我們不希望這樣,我們想從中調用一個方法。更改HookCallback到:

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
{ 
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) 
    { 
     int vkCode = Marshal.ReadInt32(lParam); 

     if (KeyPressed == vkCode) 
      DoWork(); 
    } 
    return CallNextHookEx(_HookID, nCode, wParam, lParam); 
} 

對於上面的代碼工作,我們需要添加一個新的委託和新的int變量來我們班:

private static int KeyPressed; 
public delegate void SomethingToDo(); 
private static SomethingToDo DoWork; 

SetHook也需要一些小的改動:

private static IntPtr SetHook(KeyboardProc _proc, int KeyCode, SomethingToDo GiveMeWork) 
{ 
    DoWork = GiveMeWork; 
    KeyPressed = KeyCode; 
    ...(leave the rest as it is)... 
} 

該程序現在完全不可見,可以對按鍵作出反應。讓我們做相反的事,模擬鍵!
Ctrl key kept down after simulating a ctrl key down event and ctrl key up event
這簡單得多。我做了三種方法,PressKey,ReleaseKey和TapKey。請記住,ALT和F10是可能無法使用的特殊系統鍵。

[DllImport("user32.dll", SetLastError = true)] 
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); 
private const int KeyPressCode = 0x0001; 
private const int KeyReleaseCode = 0x0002; 

    public static void PressKey(System.Windows.Forms.Keys Key) 
    { 
     keybd_event((byte)Key, 0, KeyPressCode | 0, 0); 
     Thread.Sleep(10); 
    } 

    public static void ReleaseKey(System.Windows.Forms.Keys Key) 
    { 
     keybd_event((byte)Key, 0, KeyPressCode | KeyReleaseCode, 0); 
     Thread.Sleep(10); 
    } 

    public static void TapKey(System.Windows.Forms.Keys Key) 
    { 
     PressKey(Key); 
     ReleaseKey(Key); 
    } 

就是這樣,一個基本的Autohokey-Clone可以處理字符串。如果你想走得更遠,併爲一試圖標:
https://translate.google.de/translate?sl=de&tl=en&js=y&prev=_t&hl=de&ie=UTF-8&u=https%3A%2F%2Fdotnet-snippets.de%2Fsnippet%2Fvorlage-fuer-tray-notifyicon-anwendung%2F541&edit-text=&act=url
顯示帶有按鈕的界面更是出奇的簡單:

using (Form _form = new Form()) 
{ 
    _form.size = ... 
    //.... 

    Button MyButton = new Button(); 
    //.... 
    //closing is also pretty simple, just like your everyday Windows Forms Application: 
    MyButton.Click += new EventHandler((sender, e) => { Application.Exit(); }); 

    _form.ShowDialog(); 
} 

在main方法放在一起的一切:

private static NotifyIcon TrayIcon = new NotifyIcon(); 

    [STAThread] 
    static void Main(string[] args) 
    { 

     bool WindowOpen = true; 

     try 
     { 
      //Make a new method above or below Main() and replace DoSomething with it. 
      //It will be executed everytime the F2 key is pressed. 
      KeyListener._HookID = KeyListener.SetHook(proc, System.Windows.Forms.Keys.F2, DoSomething); 


      System.Windows.Forms.ContextMenu SmallMenu = new System.Windows.Forms.ContextMenu(); 
      System.Windows.Forms.MenuItem MenuElement; 
      int MenuIndex = 0; 

      MenuElement = new System.Windows.Forms.MenuItem(); 
      MenuElement.Index = ++MenuIndex; 
      MenuElement.Text = "Close"; 
      MenuElement.Click += new EventHandler((sender, e) => { WindowOpen = false; System.Windows.Forms.Application.Exit(); }); 
      SmallMenu.MenuItems.Add(MenuElement); 

      TrayIcon.Icon = new System.Drawing.Icon("Ghost.ico"); 
      TrayIcon.Text = "String Compatible AHK"; 
      TrayIcon.Visible = true; 
      TrayIcon.ContextMenu = SmallMenu; 


      while (WindowOpen) 
       System.Windows.Forms.Application.Run(); 
     } 
     finally 
     { 
      TrayIcon.Dispose(); 
      KeyListener.UnhookWindowsHookEx(KeyListener._HookID); 
     } 
    }