none
Word 2007 Run-time error 4198 RRS feed

  • Question

  • Hi,

     I’m trying run a macro embedded in a Word document using C#, but Word pops up with the following error:

    Run-time error ‘4198’:
    Command Failed

     

    object m_fileName = "C:\\Users\\me\\AppData\\Local\\Project\\Cache\\ _SFD00_\\_SFD0000_Test.docx"; 
    object s_false = false;
    object s_missing = System.Reflection.Missing.Value;
    m_wordApp.Run("FileSaveAs", ref m_fileName, ref s_false, ref s_missing, ref s_missing, ref s_missing, ref s_missing,
    ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing,
    ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing,
    ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing);

     

    Public Sub FileSaveAs(ByRef filePath, ByRef falseObj)
    '
    ' FileSaveAs Macro
    ' Saves a copy of the document in a separate file
    '
    ActiveDocument.SaveAs FileName:=filePath, AddToRecentFiles:=falseObj
    End Sub

     

     

    It fails at ActiveDocument.SaveAs line. I’ve checked the file path while debugging the macro and it looks the same as the above minus the double slashes. Also I have very little experience with Visual Basic, so I’m not sure if I’m doing something wrong there. Any help would be appreciated and sorry for some of the crazy page formatting.

    Thanks,

    chrrug1524

     



    Monday, August 8, 2011 6:47 PM

Answers

  • Hi chrrug

    <<My only reasoning for trying to have the macro save the document was I thought maybe if I had something attached to the document directly the save would have more success, but obviously I was wrong. I’ve also had several threading issues throughout this whole process, so I’m not sure if maybe that is still the problem. >>

    OK, I think I'm with you, more or less. Office apps don't really support "threading", so this could, indeed, be an issue. If you can take that out of the equation in a fairly simple manner for testing purposes, you should try that. It's seems the most likely suspect, given the results of my other suggestions.

    It could also (and this would be related to threading) be a timing issue. Normally, using the Show method for a Windows Form should stop things and a Timer wouldn't be necessary. Given the "threading", I can see where you might attempt using a Timer. But it's possible that things still aren't accessible (the document is still "locked" somehow).

    FWIW it's possible to "repurpose" Word's FileSaveAs dialog box to a limited extent, through late-binding. You can get the selected path and file name, and whether the user clicked Cancel...


    Cindy Meister, VSTO/Word MVP
    • Marked as answer by chrrug1524 Monday, August 15, 2011 1:29 PM
    Wednesday, August 10, 2011 2:50 PM
    Moderator

All replies

  • Hi chrrug

    Command failed means, literally, that Word for some reason couldn't do what you asked it to do. Too bad it never tells you WHY... <sigh>

    One thing I'd try is to remove the ByRef in the method signature. In general terms, Office works better if you just let it do its thing. You aren't manipulating this information in any way so it shouldn't matter to you whether things go in byref or byval. Let Word decide what it prefers.

    The other thing I'd try is to make a copy of the procedure - FileSaveAs_Test for example, remove the parameters, add a variable and assign it the path, then see if the macro itself will run in the Word UI. (Just press F5.) You're testing that the document can be saved, or not.

    The try calling this from the .NET code (not passing any parameters, just calling the macro in the context of your code). This will tell you if your code is putting Word in a state where it can't save.

    If that works, put one parameter back into the "test" macro and, if that works, the other.

    If that also works then the problem may be with the name you've given the macro. FileSaveAs is an internal Word command, but the method signature has no parameters. In Word, as a VBA programmer, you can override (repurpose) internal commands by create a Public Sum CommandName() procedure with your code. It's possible that Word doesn't like how you're using its internal command and/or you're running into a conflict with it.


    Cindy Meister, VSTO/Word MVP
    Tuesday, August 9, 2011 8:04 AM
    Moderator
  • Hi Cindy,

    Thanks for the reply. I tried removing the ByRef from the method parameters, but that didn’t work and I still got the same ‘command failed’ error. However, when I ran the macro in Word with the parameters removed and the values hard coded it worked, so the document can be saved. Then I tried calling that same macro (without the parameters) from C#, but I still get the same error, so I guess that means Word is in a state where it can’t save. I also tried changing the macro/method name, but that doesn’t seem to help either. So I guess my question is where do I go from here?

    Thanks again,

    chrrug1524
    Tuesday, August 9, 2011 1:39 PM
  • Could you show us more of the context of that code? What's your application actually doing to / with the document up to that point?

    And why wouldn't you just use m_wordApp.ActiveDocument.SaveAs method? Why do you need to run a macro in Word that essentially does something you can do in your code?


    Cindy Meister, VSTO/Word MVP
    Tuesday, August 9, 2011 2:20 PM
    Moderator
  • Our training application controls the opening and saving of the Word document, the user does the rest, but I will try my best to explain the save process.

    Okay, basically we have a need to replace the standard Windows file dialog that pops up when you do a Save As in Word with our own file dialog which is able to track the user’s actions. Our dialog also uses a fake file system so when the user saves to any location, that isn’t necessarily where we want the real file to go. I know that part is sort of confusing and probably sounds hacky…but basically all I’m trying to do is save the file to a specific location.

    So first in Word’s BeforeSave event, I prevent the standard dialog from opening and then open our own.

     

    private Document m_currentDoc = null;
    private SynchronizationContext m_syncContext;
    
    void wordEvents_DocumentBeforeSave(Document Doc, ref bool SaveAsUI, ref bool Cancel)
    {
          m_currentDoc = Doc;
          SaveAsUI = false;
          Cancel = true;
    
            try
            {
              //Ensure that the creation of file dialog occurs on the GUI Thread
              m_syncContext.Send(_ =>
              {
                //Create file dialog instance here;
              }
              , null);
            }
            catch (Exception e)
            {
              System.Windows.Forms.MessageBox.Show(e.ToString());
            }
    }
    
    

    Our file dialog has its own callback where I create a background timer that attempts to execute the Word macro after a couple of seconds.

     

    private TimerCallback m_timerCallback;
    private Timer m_timer = null;
    
    private void CheckDialogResult()
    {
              //This is what I was trying to explain earlier, so while the user is saving a fake file to a certain location,
              // this is where I want the real file to go
                   
              m_fileName = "C:\\Users\\me\\AppData\\Local\\Project\\Cache\\ _SFD00_\\_SFD0000_Test.docx";
    
              try
              {
                m_timerCallback += new TimerCallback(TrySave);
                
                m_timer = new Timer(m_timerCallback, null, 2000, Timeout.Infinite);            
              }
              catch (Exception e)
              {            
                System.Windows.Forms.MessageBox.Show(e.ToString());            
              }     
    }
    
    

    Now after the timer is up it calls the following method where I try to run the macro.

     

    private void TrySave(object data)
    {
          try
          {
            m_wordApp.Run("TestSave", ref m_fileName, ref s_false, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing,
                  ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing,
                  ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing,
                  ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing, ref s_missing);
    
            
            m_timer.Dispose();
            
          }
          catch (Exception e)
          {
            System.Windows.Forms.MessageBox.Show(e.ToString());        
          }
    }
    
    

     

    Before trying this method I actually tried what you suggested by replacing the m_wordApp.Run with m_currentDoc.SaveAs, but it results in the same ‘command failed’ error except it pops up on the C# side. My only reasoning for trying to have the macro save the document was I thought maybe if I had something attached to the document directly the save would have more success, but obviously I was wrong. I’ve also had several threading issues throughout this whole process, so I’m not sure if maybe that is still the problem. Let me know if something isn’t clear, I can try to clarify.

    Thanks,

    chrrug1524

     

    Wednesday, August 10, 2011 2:01 PM
  • Hi chrrug

    <<My only reasoning for trying to have the macro save the document was I thought maybe if I had something attached to the document directly the save would have more success, but obviously I was wrong. I’ve also had several threading issues throughout this whole process, so I’m not sure if maybe that is still the problem. >>

    OK, I think I'm with you, more or less. Office apps don't really support "threading", so this could, indeed, be an issue. If you can take that out of the equation in a fairly simple manner for testing purposes, you should try that. It's seems the most likely suspect, given the results of my other suggestions.

    It could also (and this would be related to threading) be a timing issue. Normally, using the Show method for a Windows Form should stop things and a Timer wouldn't be necessary. Given the "threading", I can see where you might attempt using a Timer. But it's possible that things still aren't accessible (the document is still "locked" somehow).

    FWIW it's possible to "repurpose" Word's FileSaveAs dialog box to a limited extent, through late-binding. You can get the selected path and file name, and whether the user clicked Cancel...


    Cindy Meister, VSTO/Word MVP
    • Marked as answer by chrrug1524 Monday, August 15, 2011 1:29 PM
    Wednesday, August 10, 2011 2:50 PM
    Moderator
  • After banging my head against the wall for quite a while I think I have come up with a solution that removes a portion of the threading from this equation. I’m able to save the document in Word’s DocumentBeforeSave method, so basically this gave me the idea that maybe I could do things sort of backwards. So I start out by saving the document when the user clicks Save As to a temporary file name. Then I open our file dialog and the user saves the file to their desired location and I then use the file name they saved with to rename the temporary file. So far this approach seems to be working, but regardless thank you for your help.

    Regards,

    chrrug1524
    Monday, August 15, 2011 1:29 PM
  • try this

    WordApp.ChangeFileOpenDirectory("C:\SomeFolder\")

    Doc_Name = "File.doc"

    oDoc.SaveAs2(FileName:=Doc_Name, FileFormat:=0, LockComments:=False, Password:="", AddToRecentFiles:=False, WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:=False, CompatibilityMode:=0)


    • Edited by Sopas1284 Tuesday, May 14, 2019 10:08 PM
    Tuesday, May 14, 2019 10:05 PM