none
Trying to save a wave file to using mciSendString RRS feed

  • Question

  • Hello,

    VS C# 2008 SP1

    I have a created a small application that records and plays audio. However, my application needs to save the wave file to the application data directory on the users computer.

    The mciSendString takes a C style string as a parameter and has to be in 8.3 format. However, my problem is I can't get it to save. And what is strange is sometime it does and sometimes it doesn't. Howver, most of the time is failes. However, if I save directly to the C drive it works first time everything. I have used 3 different methods that I have coded below.

    The error number that I get when it fails is 286."The file was not saved. Make sure your system has sufficient disk space or has an intact network connection"

    Many thanks for any suggestions,

     [DllImport("winmm.dll",CharSet=CharSet.Auto)]
            private static extern uint mciSendString([MarshalAs(UnmanagedType.LPTStr)] string command,
                                                     StringBuilder returnValue,
                                                     int returnLength,
                                                     IntPtr winHandle);
    
            [DllImport("winmm.dll", CharSet = CharSet.Auto)]
            private static extern int mciGetErrorString(uint errorCode, StringBuilder errorText, int errorTextSize);
    
            [DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
            private static extern int GetShortPathName([MarshalAs(UnmanagedType.LPTStr)] string longPath,
                                                       [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,
                                                        int length);
    
     // Stop recording
            private void StopRecording()
            {
                // Save recorded voice
                string shortPath = this.shortPathName();
                string formatShortPath = string.Format("save recsound \"{0}\"", shortPath);
                uint result = 0;
                StringBuilder errorTest = new StringBuilder(256);
                
                // C:\DOCUME~1\Steve\APPLIC~1\Test.wav
                result = mciSendString(string.Format("{0}", formatShortPath), null, 0, IntPtr.Zero);
                mciGetErrorString(result, errorTest, errorTest.Length);
    
                // command line convention
                result = mciSendString("save recsound \"C:\\DOCUME~1\\Steve\\APPLIC~1\\Test.wav\"", null, 0, IntPtr.Zero);
                mciGetErrorString(result, errorTest, errorTest.Length);         
    
                // 8.3 short format
                result = mciSendString(@"save recsound C:\DOCUME~1\Steve\APPLIC~1\Test.wav", null, 0, IntPtr.Zero);
                mciGetErrorString(result, errorTest, errorTest.Length);
    
                // Save to C drive works everytime.
                result = mciSendString(@"save recsound C:\Test.wav", null, 0, IntPtr.Zero);
                mciGetErrorString(result, errorTest, errorTest.Length);
    
                mciSendString("close recsound ", null, 0, IntPtr.Zero);
     }
    
    // Get the short path name so that the mciSendString can save the recorded wave file
            private string shortPathName()
            {
                string shortPath = string.Empty;
                long length = 0;
                StringBuilder buffer = new StringBuilder(256);
    
                // Get the length of the path 
                length = GetShortPathName(this.saveRecordingPath, buffer, 256);
               
                shortPath = buffer.ToString();
             
                return shortPath;
            }
    

     

    Saturday, July 18, 2009 4:59 PM

All replies

  • Since the save has demonstrated that it works, it is then with how you path to the location. Does a save fail at one level but not another in the directory structure?

     First off you need to extract out the save functionality. Create a method which takes a path and a file name. Combine those two and then save within the function. Once that is working call the method with a list of directories to try.  Call it with a set list and report back what fails. YOur code above is confusing. Just boil it down to the facts of which directories are working and which fail. Here is an example of setting up that list, notice I am using the @ to make the text literal so one does have to escape the slash (\\):

                List<string> targets = new List<string>()  
                     { @"C:\", 
                       @"C:\Level1\", 
                       @"C:\Level1 Long\", 
                       @"C:\DOCUME~1\" 
                     } ;
    



    This way you can test what fails and what works. I surmise you will find its a problem with either the actual name of the path or the escaping in C# is not being handled in the application. (Either one to many \'s or not enough).


    GL and report back on a list of which works and which fails. Try every cobination. GL


    William Wegerson (www.OmegaCoder.Com)
    Saturday, July 18, 2009 8:05 PM
    Moderator
  • Hello,

    Thanks for the response. I have tested the different levels and this is my results from testing. From the results below all the tests fail on saving at the ApplicationData (APPLIC~1) level. So I can save at level Steve but can't go any further.

    I have added and removed the escape character and used the @, and vice versa.

    Results that Fail:
    result = mciSendString("save recsound \"C:\\DOCUME~1\\Steve\\APPLIC~1\\Test.wav\"", null, 0, IntPtr.Zero);
    
    result = mciSendString(@"save recsound C:\DOCUME~1\Steve\APPLIC~1\Test.wav", null, 0, IntPtr.Zero);

    Results that pass:
    result = mciSendString("save recsound \"C:\\DOCUME~1\\Steve\\Test.wav\"", null, 0, IntPtr.Zero)
    result = mciSendString(@"save recsound C:\DOCUME~1\Steve\Test.wav", null, 0, IntPtr.Zero);
    So, as you can see from the results, I am able to save to the Steve directory, but cannot save to the application data directory. Their is nothing wrong with that path, as I can browse to that in a window.

    Many thanks for any more suggestions,

    • Edited by steve1_rm Sunday, July 19, 2009 1:33 PM
    Sunday, July 19, 2009 1:26 PM
  • Hi Steve,

    I am not convinced you are handling the setting up the path to a filename in a uniform fashion. Did you create a method and pass in the directory to be combined with the file? Because I see two different string handling methods here

    ("save recsound \"C:\\DOCUME~1\\Steve\\APPLIC~1\\Test.wav\"", ...

    to

    (@"save recsound C:\DOCUME~1\Steve\APPLIC~1\Test.wav", null,

    If the second one fails does it work as you do with the first one?

    I don't mean to be picky, but doing two different calls is apples and oranges for debugging purposes. Put all paths strings in a list, enumerate that list and call one function to combine the path with the file name and then and only then send it to mciSendString. Report back on the list you created and which failed and which succeded.

    By looking at your last post, it appears that the directory needs to be in quotes, which you did for the first one but the second one ...hence one must be consistent. HTH

    William Wegerson (www.OmegaCoder.Com)
    Sunday, July 19, 2009 6:25 PM
    Moderator
  • Hello William,

    I have created a list and function that will combine a path and a filename.

    List<string> targets = new List<string>()
            {
                @"C:\",
                @"C:\DOCUME~1\",
                @"C:\Steve\",
                @"C:\APPLIC~1\"
            };
    
            private void getDirectory(string path, string filename)
            {
                // directory = C:\DOCUME~1\Steve\APPLIC~1\
                // filename = Test.wav
                uint result = 0;
                StringBuilder errorTest = new StringBuilder(256);
                string directory = System.IO.Path.Combine(path, filename);
    
                result = mciSendString("save recsound " + directory, null, 0, IntPtr.Zero);
                mciGetErrorString(result, errorTest, errorTest.Length);         
            }
    Now, I have my list, but not exactly sure how to use in the above example. Could you please explain further with more sample code?

    Many thanks for your help,

    Steve




    Monday, July 20, 2009 4:03 PM
  • http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/8a9b062d-ade6-4365-8516-e12cc20eb915

    Could the 8.3 filenames be goofing it up?
    Mark the best replies as answers. "Fooling computers since 1971."
    Monday, July 20, 2009 4:30 PM
    Moderator
  • I have created a list and function that will combine a path and a filename.Now, I have my list, but not exactly sure how to use in the above example. Could you please explain further with more sample code?
    I would have GetDirectory return a status string of the error if it exists. Now just enumerate (foreach) over the list and call GetDirectory and report what works and what doesn't



    William Wegerson (www.OmegaCoder.Com)
    Monday, July 20, 2009 4:33 PM
    Moderator
  • Hello William,

    Here is the result of the testing. Where 0 would indicate success and 286 means "The file was not saved. Make sure your system has sufficient disk space or has an intact network connection."

    Item: [ C:\ ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\test.wav ]
    Item: [ C:\DOCUME~1\ ] rtnMsg: [ 0 ]
    Directory path: [ C:\Steve\test.wav ]
    Item: [ C:\Steve\ ] rtnMsg: [ 286 ]
    Directory path: [ C:\APPLIC~1\test.wav ]
    Item: [ C:\APPLIC~1\ ] rtnMsg: [ 286 ]
    My coding below:

    List<string> targets = new List<string>()
            {
                @"C:\",
                @"C:\DOCUME~1\",
                @"C:\Steve\",
                @"C:\APPLIC~1\"
            };
    
            private void StopSaveRecording()
            {
                int rtnResult = 0;
    
                foreach (string item in targets)
                {
                    rtnResult = this.getDirectory(item, "test.wav");
                    
                    Console.WriteLine(string.Format("Item: [ {0} ] rtnMsg: [ {1} ]", 
                        item, rtnResult));    
                }
            }
    
            private int getDirectory(string path, string filename)
            {
                uint result = 0;
                StringBuilder errorTest = new StringBuilder(256);
                string directory = System.IO.Path.Combine(path, filename);
                Console.WriteLine(string.Format("Directory path: [ {0} ]", directory));
                result = mciSendString("save recsound " + directory, null, 0, IntPtr.Zero);
                
                return (int) result;
            }
        }

    Many thanks for your help.

    Any further instructions I can do to solve this problem?

    Thanks,







    Tuesday, July 21, 2009 3:38 PM
  • What happens on a negative test where you would say

    @"C:\\Steve\\",

    I am wondering if the double escapes are needed for the wave processor....what is the commonality of failures? Add more tests.

    William Wegerson (www.OmegaCoder.Com)
    Tuesday, July 21, 2009 4:28 PM
    Moderator
  • Hello William,

    I am completed more testing. These are my latest results.

    I remove the @ from the list and tested on the same directory structure. The test failed to save to the application data folder see below.
    List<string> targets = new List<string>()
    {
    "C:\\",
    "C:\\DOCUME~1",
    "C:\\DOCUME~1\\Steve",
    "C:\\DOCUME~1\\Steve\\APPLIC~1"
    };

    Directory path: [ C:\test.wav ]
    Item: [ C:\ ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\test.wav ]
    Item: [ C:\DOCUME~1 ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\Steve\test.wav ]
    Item: [ C:\DOCUME~1\Steve ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\Steve\APPLIC~1\test.wav ]
    Item: [ C:\DOCUME~1\Steve\APPLIC~1 ] rtnMsg: [ 286 ]

    I then created this directory  C:\DOCUME~1\Admini~1\Files. Which also failed to save
    List<string> targets = new List<string>()
    {
    "C:\\",
    "C:\\DOCUME~1",
    "C:\\DOCUME~1\\Admini~1",
    "C:\\DOCUME~1\\Admini~1\\Files"
    };

    Directory path: [ C:\test.wav ]
    item: [ C:\ ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\test.wav ]
    Item: [ C:\DOCUME~1 ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\Admini~1\test.wav ]
    Item: [ C:\DOCUME~1\Admini~1 ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\Admini~1\Files\test.wav ]
    Item: [ C:\DOCUME~1\Admini~1\Files ] rtnMsg: [ 286 ]

    I then created this directory C:\path1\path2\path3\path4 which is 4 deep. And this saved the wave file in the path4 directory. So this test passed.
    List<string> targets = new List<string>()
    {
    "C:\\",
    "C:\\path1",
    "C:\\path1\\path2",
    "C:\\path1\\path2\\path3\\path4"
    };
    Directory path: [ C:\test.wav ]
    Item: [ C:\ ] rtnMsg: [ 0 ]
    Directory path: [ C:\path1\test.wav ]
    Item: [ C:\path1 ] rtnMsg: [ 0 ]
    Directory path: [ C:\path1\path2\test.wav ]
    Item: [ C:\path1\path2 ] rtnMsg: [ 0 ]
    Directory path: [ C:\path1\path2\path3\path4\test.wav ]
    Item: [ C:\path1\path2\path3\path4 ] rtnMsg: [ 0 ]

    I then created this directory from the 'document and settings' C:\Documents and Settings\doc1\doc2. this also passed and saved the wave file.
    List<string> targets = new List<string>()
    {
    "C:\\",
    "C:\\DOCUME~1",
    "C:\\DOCUME~1\\doc1",
    "C:\\DOCUME~1\\doc1\\doc2"
    };
    Directory path: [ C:\test.wav ]
    Item: [ C:\ ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\test.wav ]
    Item: [ C:\DOCUME~1 ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\doc1\test.wav ]
    Item: [ C:\DOCUME~1\doc1 ] rtnMsg: [ 0 ]
    Directory path: [ C:\DOCUME~1\doc1\doc2\test.wav ]
    Item: [ C:\DOCUME~1\doc1\doc2 ] rtnMsg: [ 0 ]

    In conclusion I seems I can save in most places but not when I try and save in my Steve or Administrator directory.

    I am compiling on windows XP SP3.

    Many thanks for any other suggestions you might have about this.

    Thanks,
    • Edited by steve1_rm Wednesday, July 22, 2009 5:27 PM
    Wednesday, July 22, 2009 5:23 PM
  • I can see it failing in the admin directory, but nor your Steve , because the account which is running the process doesn't have privileges. Check privileges on the directories in question and see if there is a difference. Maybe by allowing your account (which I presume is running the operation) expanded privileges on those directories that might solve the problem.

    Regardless, you may want to anticipate this problem and ask the user to save to a different location.

    William Wegerson (www.OmegaCoder.Com)
    Wednesday, July 22, 2009 6:03 PM
    Moderator
  • Hello William,

    Thanks for all your help.

    I have completed a new test by hard coding the path. This worked:

    result = mciSendString("save recsound \"C:\\DOCUME~1\\steve\\APPLIC~1\\Test.wav\"", null, 0, IntPtr.Zero);
    I don't think it has something to do with permissions.

    The test I have done by hard coding worked well today and I have done many runs and it worked every time.

    Have you done any similar tests like above on your computer?

    Many thanks if you have any more suggestions.

    Thanks,


    Thursday, July 23, 2009 3:42 PM
  • Did you got answer for this question??? If YES, please let me know.
    Monday, May 20, 2019 4:03 PM
  • TEN years.  That's how old this thread is.  The people involved are all long gone.  If you have a question, please make a new posting, rather than hijacking a dead thread.

    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Tuesday, May 21, 2019 7:21 AM