#StackBounty: #asp.net #vb.net #iis #iis-8 #windows-server-2012-r2 IIS Classic Mode .NET Web API Call returns 404 Error

Bounty: 50

I have a pre-existing VB.NET web application running on IIS 8 in Windows Server 2012 R2. The application needs to handle a new API call (ex. localhost/test/ping) which I implemented using the APIController interface. I was able to successfully run the API call on my local Visual Studio, but once I deploy it to IIS, the url returns a 404 error.

After some digging and research, part of the problem I believe is the web app does not have ExtensionlessUrlHandler-Integerated-4.0 in the handler mapping. Looking into the configurations, apparently part of the pre-condition is the application cannot be me in classic mode, which mine is. I cannot switch to integrated mode which will break my app.

Is there a way around this limitation.


Update: Adding the web.config

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />
  <handlers>
    <add name="MVC" path="*." verb="*" type="" modules="IsapiModule" scriptProcessor="C:WindowsMicrosoft.NETFrameworkv2.0.50727aspnet_isapi.dll" resourceType="File" requireAccess="None" allowPathInfo="false" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="4194304" />
  </handlers>
</system.webServer>


Get this bounty!!!

#StackBounty: #vb.net #entity-framework-6 #ef-code-first #ef-migrations How does one override the default SQL migration generator?

Bounty: 50

I’m attempting to override the default behavior of the SQL migrations generator so that I may specify a custom foreign key constraint name, as discussed here. I’ve wired up the configuration as advised.

Unfortunately, however, it’s not going so well.

A quick logging statement reveals that the GetFkName() function is never hit.

I tried an alternate configuration construct, as discussed here and here, but I’m getting this error when I attempt to generate a migration:

More than one migrations configuration type was found in the assembly ‘ConsoleApp1’. Specify the name of the one to use.

I find this result a bit odd, as I have only one configuration class, one SQL generation class, and one context class (the code below doesn’t reflect this, but I commented out the extras for my actual tests). Specifying the configuration type on the command line, as indicated here, errors with this:

System.InvalidOperationException: The type ‘ConsoleApp1.Db.CustomDbConfiguration2’ does not inherit from ‘System.Data.Entity.DbConfiguration’. Entity Framework code-based configuration classes must inherit from ‘System.Data.Entity.DbConfiguration’.

All of this brings us back here, then, which doesn’t work for the aforementioned reason (GetFkName() never gets hit). So it seems I’m chasing my tail (didn’t know I had one until today).

What should I do to get this override to work correctly?


Configuration

Imports System.Data.Entity
Imports System.Data.Entity.Migrations
Imports System.Data.Entity.SqlServer

Namespace Db
  Friend Class CustomDbConfiguration
    Inherits DbConfiguration

    Public Sub New()
      Me.SetMigrationSqlGenerator(SqlProviderServices.ProviderInvariantName, Function() New CustomSqlGenerator)
    End Sub
  End Class

  Friend Class CustomDbConfiguration2
    Inherits DbMigrationsConfiguration(Of Context)

    Public Sub New()
      Me.SetSqlGenerator(SqlProviderServices.ProviderInvariantName, New CustomSqlGenerator2(Me.GetSqlGenerator(SqlProviderServices.ProviderInvariantName)))
      Me.ContextType = GetType(Context)
    End Sub
  End Class
End Namespace

SQL Generator

Imports System.Data.Entity.Migrations.Model
Imports System.Data.Entity.Migrations.Sql
Imports System.Data.Entity.SqlServer

Namespace Db
  Friend Class CustomSqlGenerator
    Inherits SqlServerMigrationSqlGenerator

    Protected Overrides Sub Generate(AddForeignKeyOperation As AddForeignKeyOperation)
      AddForeignKeyOperation.Name = GetFkName(AddForeignKeyOperation.PrincipalTable, AddForeignKeyOperation.DependentTable, AddForeignKeyOperation.DependentColumns.ToArray())
      MyBase.Generate(AddForeignKeyOperation)
    End Sub

    Protected Overrides Sub Generate(DropForeignKeyOperation As DropForeignKeyOperation)
      DropForeignKeyOperation.Name = GetFkName(DropForeignKeyOperation.PrincipalTable, DropForeignKeyOperation.DependentTable, DropForeignKeyOperation.DependentColumns.ToArray())
      MyBase.Generate(DropForeignKeyOperation)
    End Sub

    Private Shared Function GetFkName(PrimaryKeyTable As String, ForeignKeyTable As String, ParamArray ForeignTableFields As String()) As String
      IO.File.WriteAllText("D:LogsFkNameTest.log", $"{Now.ToString}{vbCrLf}")

      Return $"FK_{ForeignKeyTable}_{PrimaryKeyTable}"
    End Function
  End Class

  Friend Class CustomSqlGenerator2
    Inherits MigrationSqlGenerator

    Public Sub New(Generator As MigrationSqlGenerator)
      Me.Generator = Generator
    End Sub

    Public Overrides Function Generate(MigrationOperations As IEnumerable(Of MigrationOperation), ProviderManifestToken As String) As IEnumerable(Of MigrationStatement)
      Return Me.Generator.Generate(MigrationOperations, ProviderManifestToken)
    End Function

    Private ReadOnly Generator As MigrationSqlGenerator
  End Class
End Namespace

Context

Imports System.Data.Common
Imports System.Data.Entity
Imports System.Data.SqlClient
Imports System.Reflection

Namespace Db
  <DbConfigurationType(GetType(CustomDbConfiguration2))>
  Friend Class Context
    Inherits DbContext

    Public Sub New()
      MyBase.New(DbConnection.ConnectionString)
    End Sub

    Private Sub New(Connection As DbConnection)
      MyBase.New(Connection, True)

      Database.SetInitializer(New CreateDatabaseIfNotExists(Of Context))
      Database.SetInitializer(New MigrateDatabaseToLatestVersion(Of Context, Migrations.Configuration))

      Me.Database.Initialize(False)
    End Sub

    Public Shared Function Create() As Context
      Return New Context(DbConnection)
    End Function

    Private Shared ReadOnly Property DbConnection As SqlConnection
      Get
        Return New SqlConnection(Utils.DbConnectionString)
      End Get
    End Property

    Protected Overrides Sub OnModelCreating(Builder As DbModelBuilder)
      Builder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly)
      MyBase.OnModelCreating(Builder)
    End Sub

    Public Property Documents As DbSet(Of Document)
    Public Property Sections As DbSet(Of Section)
  End Class
End Namespace


Get this bounty!!!

#StackBounty: #c# #vb.net #entity-framework-6 #ef-migrations #fluent How can I set the foreign key name using the Fluent API with Code …

Bounty: 100

I’m trying to set the foreign key name (not the foreign key column) using Code First Migrations on EF6.4.

I know that it can be set by updating the generated migration code, like so:

.ForeignKey("Documents", Function(t) t.DocumentId, cascadeDelete:=True, name:="FK_Sections_Documents")

…but I’d like to do it before the migration is added, using the Fluent API.

I seem to recall something about the HasForeignKey() call accepting a Func that contains a call to an anonymous type in its body, such as what we find here. But I’ll be darned if I can locate anything discussing what the general structure of that type should be.

The official documentation doesn’t discuss it:

Nor do these similar Q&As quite exactly address the issue:

This same question was asked a couple of months ago here, but so far it hasn’t received an answer.

I’m using EntityTypeConfiguration(Of T). Here’s my code:

Namespace Configuration
  Friend Class SectionConfig
    Inherits EntityTypeConfiguration(Of Db.Section)

    Public Sub New()
      Me.HasRequired(Function(Section) Section.Document).WithMany.HasForeignKey(Function(Section) Section.DocumentId)

      Me.Property(Function(Section) Section.DocumentId).IsRequired()
      Me.Property(Function(Section) Section.SectionId).IsRequired()
      Me.Property(Function(Section) Section.IsSent).IsRequired()
      Me.Property(Function(Section) Section.Markup).IsRequired.IsMaxLength()
      Me.Property(Function(Section) Section.Title).IsRequired.HasMaxLength(60)

      Me.HasIndex(Function(Section) Section.DocumentId).HasName("IX_Sections_DocumentId")
      Me.HasIndex(Function(Section) Section.SectionId).HasName("IX_Sections_SectionId")
      Me.HasIndex(Function(Section) Section.Title).HasName("IX_Sections_Title")

      Me.Ignore(Function(Section) Section.Subject)
    End Sub
  End Class
End Namespace

How does one set a foreign key name, or—even more specific, assuming I’m remembering correctly—what should be the general structure of that anonymous type?

–UPDATE–

I tried this:

Me.HasRequired(Function(Section) Section.Document).WithMany.HasForeignKey(Function(Section) New With {.DependentKeyExpression = Section.DocumentId, .Name = "FK_Sections_Documents"})

…but a migration creation attempt answered with this:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.InvalidOperationException: The properties expression ‘Section => new VB$AnonymousType_0`2(DependentKeyExpression = Section.DocumentId, Name = “FK_Sections_Documents”)’ is not valid. The expression should represent a property: C#: ‘t => t.MyProperty’ VB.Net: ‘Function(t) t.MyProperty’. When specifying multiple properties use an anonymous type: C#: ‘t => new { t.MyProperty1, t.MyProperty2 }’ VB.Net: ‘Function(t) New With { t.MyProperty1, t.MyProperty2 }’.

So, given that we must use properties currently existing on the entity, the anonymous type construct must not be the way to specify a foreign key name.

The question still stands: How may we specify the foreign key name using the Fluent API in EF6.4?


Get this bounty!!!

#StackBounty: #vb.net #rest #api What is wrong with this coinmex API?

Bounty: 200

Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
    Dim base = "https://www.coinmex.com"
    Dim premethod = "/api/v1/spot/ccex/"
    Dim longmethod = premethod + method

    Dim timestampstring = getEstimatedTimeStamp().ToString

    Dim stringtosign = timestampstring + "GET" + longmethod + "{}" '1553784499976GET/api/v1/spot/ccex/account/assets{}

    Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1))
    Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
    Dim signature = System.Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
    Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

    '_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
    '_passphrase1= 1Us6&f%*K@Qsqr**
    '
    Dim response = CookieAwareWebClient.downloadString1(url, "", {Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1)})

    Return response
End Function

Public Overrides Sub readbalances()
    typicalReadBalances("account/assets", "data", "currencyCode", "available", "frozen", "", {})
End Sub

I think I did it like what’s listed here
https://github.com/coinmex/coinmex-official-api-docs/blob/master/README_EN.md#1-access-account-information

# Request
GET /api/v1/spot/ccex/account/assets

# Response
[
    {
        "available":"0.1",
        "balance":"0.1",
        "currencyCode":"ETH",
        "frozen":"0",
        "id":1
    },
    {
        "available":"1",
        "balance":"1",
        "currencyCode":"USDT",
        "frozen":"0",
        "id":1
    }
]

And for Signature

This is the manual says

The ACCESS-SIGN header is the output generated by using HMAC SHA256 to
create the HMAC SHA256 using the BASE64 decoding secret key in the
prehash string to generate timestamp + method + requestPath + “?” +
queryString + body (where ‘+’ represents the string concatenation) and
BASE64 encoded output. The timestamp value is the same as the
ACCESS-TIMESTAMP header. This body is the request body string or
omitted if there is no request body (usually the GET request). This
method should be capitalized.

Remember that before using it as the key to HMAC, base64 decoding (the
result is 64 bytes) is first performed on the 64-bit alphanumeric
password string. In addition, the digest output is base64 encoded
before sending the header.

User submitted parameters must be signed except for sign. First, the
string to be signed is ordered according to the parameter name (first
compare the first letter of all parameter names, in alphabetic order,
if you encounter the same first letter, then you move to the second
letter, and so on).

For example, if we sign the following parameters

curl "https://www.coinmex.com/api/v1/spot/ccex/orders?limit=100"       

Timestamp = 1590000000.281
Method = "POST"
requestPath = "/api/v1/spot/ccex/orders"
queryString= "?limit=100"
body = {
            'code': 'ct_usdt',
            'side': 'buy',
            'type': 'limit',
            'size': '1',
            'price': '1',
            'funds': '',
        }

Generate the string to be signed

Message = '1590000000.281GET/api/v1/spot/ccex/orders?limit=100{"code": "ct_usdt", "side": "buy", "type": "limit", "size": "1", "price": "0.1", "funds": ""}'

Then, the character to be signed is added with the private key
parameters to generate the final character string to be signed.

For example:

hmac = hmac(secretkey, Message, SHA256)
Signature = base64.encode(hmac.digest())

I thought may be the _secret1 is a base64 string rather than utf8 so I changed to

Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

'Dim stringtosign = timestampstring + "GET" + longmethod + "{}" '1553784499976GET/api/v1/spot/ccex/account/assets{} also doesn't work
Dim stringtosign = timestampstring + "GET" + longmethod  '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(_secret1)) 'secret looks like 43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsq***
'
Dim response = CookieAwareWebClient.downloadString1(url, "", {Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1)})

Return response

Not working either.

The secret key (I truncated a few letters) look like

43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2

Is this something that should be decoded as base 64 or utf8 or what?

The spec says it’s 64. However, it doesn’t look like a 64 encoded string. It looks like the letters are from 0-f

Best answers will:
1. Tell me what went wrong in the code. I made the change. Try. Run. Works. Awesome.

A good answer will
2. A sample simulation with a fake/real signatures/nonce/passphrase and real actual headers and signatures. So I can see where exactly I have a wrong result.


Get this bounty!!!

#StackBounty: #c# #vb.net #rest #api What is wrong with this coinmex API?

Bounty: 200

Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
    Dim base = "https://www.coinmex.com"
    Dim premethod = "/api/v1/spot/ccex/"
    Dim longmethod = premethod + method

    Dim timestampstring = getEstimatedTimeStamp().ToString

    Dim stringtosign = timestampstring + "GET" + longmethod + "{}" '1553784499976GET/api/v1/spot/ccex/account/assets{}

    Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1))
    Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
    Dim signature = System.Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
    Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

    '_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
    '_passphrase1= 1Us6&f%*K@Qsqr**
    '
    Dim response = CookieAwareWebClient.downloadString1(url, "", {Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1)})

    Return response
End Function

Public Overrides Sub readbalances()
    typicalReadBalances("account/assets", "data", "currencyCode", "available", "frozen", "", {})
End Sub

I think I did it like what’s listed here
https://github.com/coinmex/coinmex-official-api-docs/blob/master/README_EN.md#1-access-account-information

# Request
GET /api/v1/spot/ccex/account/assets

# Response
[
    {
        "available":"0.1",
        "balance":"0.1",
        "currencyCode":"ETH",
        "frozen":"0",
        "id":1
    },
    {
        "available":"1",
        "balance":"1",
        "currencyCode":"USDT",
        "frozen":"0",
        "id":1
    }
]

And for Signature

This is the manual says

The ACCESS-SIGN header is the output generated by using HMAC SHA256 to
create the HMAC SHA256 using the BASE64 decoding secret key in the
prehash string to generate timestamp + method + requestPath + “?” +
queryString + body (where ‘+’ represents the string concatenation) and
BASE64 encoded output. The timestamp value is the same as the
ACCESS-TIMESTAMP header. This body is the request body string or
omitted if there is no request body (usually the GET request). This
method should be capitalized.

Remember that before using it as the key to HMAC, base64 decoding (the
result is 64 bytes) is first performed on the 64-bit alphanumeric
password string. In addition, the digest output is base64 encoded
before sending the header.

User submitted parameters must be signed except for sign. First, the
string to be signed is ordered according to the parameter name (first
compare the first letter of all parameter names, in alphabetic order,
if you encounter the same first letter, then you move to the second
letter, and so on).

For example, if we sign the following parameters

curl "https://www.coinmex.com/api/v1/spot/ccex/orders?limit=100"       

Timestamp = 1590000000.281
Method = "POST"
requestPath = "/api/v1/spot/ccex/orders"
queryString= "?limit=100"
body = {
            'code': 'ct_usdt',
            'side': 'buy',
            'type': 'limit',
            'size': '1',
            'price': '1',
            'funds': '',
        }

Generate the string to be signed

Message = '1590000000.281GET/api/v1/spot/ccex/orders?limit=100{"code": "ct_usdt", "side": "buy", "type": "limit", "size": "1", "price": "0.1", "funds": ""}'

Then, the character to be signed is added with the private key
parameters to generate the final character string to be signed.

For example:

hmac = hmac(secretkey, Message, SHA256)
Signature = base64.encode(hmac.digest())

I thought may be the _secret1 is a base64 string rather than utf8 so I changed to

Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

'Dim stringtosign = timestampstring + "GET" + longmethod + "{}" '1553784499976GET/api/v1/spot/ccex/account/assets{} also doesn't work
Dim stringtosign = timestampstring + "GET" + longmethod  '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(_secret1)) 'secret looks like 43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsq***
'
Dim response = CookieAwareWebClient.downloadString1(url, "", {Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1)})

Return response

Not working either.

The secret key (I truncated a few letters) look like

43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2

Is this something that should be decoded as base 64 or utf8 or what?

The spec says it’s 64. However, it doesn’t look like a 64 encoded string. It looks like the letters are from 0-f

Best answers will:
1. Tell me what went wrong in the code. I made the change. Try. Run. Works. Awesome.

A good answer will
2. A sample simulation with a fake/real signatures/nonce/passphrase and real actual headers and signatures. So I can see where exactly I have a wrong result.


Get this bounty!!!

#StackBounty: #vb.net #wmplib List and Select Sound Card to Play Sound

Bounty: 50

I have a school bell project coded with Visual Basic 2010 Express. The computer which runs my program has two or more sound cards. First I will list the sound cards to user. User will select the sound card to work. Finally my program will ring the bells on that sound card. Everything is okey for my codes but i can’t list the names of sound cards and ring the bell on specified sound card.

I use WMPLib to play music. I have these codes but there becomes an error “the value is not in the expected range”. I spotted where the error is in my codes:

    Public Declare Function waveOutGetNumDevs Lib "winmm" () As Integer
    Public Declare Function mciSendCommand Lib "winmm.dll" Alias "mciSendCommandA" (ByVal wDeviceID As Integer, ByVal uMessage As String, ByVal dwParam1 As Integer, ByVal dwParam2 As Object) As Integer
    Public Declare Function mciGetErrorString Lib "winmm.dll" Alias "mciGetErrorStringA" (ByVal dwError As Integer, ByVal lpstrBuffer As String, ByVal uLength As Integer) As Integer
    Public Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer
    Public Declare Function mciGetDeviceID Lib "winmm.dll" Alias "mciGetDeviceIDA" (ByVal lpstrName As String) As Integer

Public Const MMSYSERR_NOERROR = 0
    Public Const MCI_SET = &H80D
    Public Const MCI_WAVE_OUTPUT = &H800000
    Public Structure MCI_WAVE_SET_PARMS
        Dim dwCallback As Integer
        Dim dwTimeFormat As Integer
        Dim dwAudio As Integer
        Dim wInput As Integer
        Dim wOutput As Integer
        Dim wFormatTag As Short
        Dim wReserved2 As Short
        Dim nChannels As Short
        Dim wReserved3 As Short
        Dim nSamplesPerSec As Integer
        Dim nAvgBytesPerSec As Integer
        Dim nBlockAlign As Short
        Dim wReserved4 As Short
        Dim wBitsPerSample As Short
        Dim wReserved5 As Short
    End Structure

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim parms As MCI_WAVE_SET_PARMS
        Dim wDeviceID As Integer
        Dim ret As Integer

        parms.wOutput = 0

        wDeviceID = mciGetDeviceID("waveaudio")

        ' the value is not in the expected range error is here and it spots parms
        ret = mciSendCommand(wDeviceID, MCI_SET, MCI_WAVE_OUTPUT, parms)

        If (ret <> MMSYSERR_NOERROR) Then
            Stop
        End If

        If ofd.ShowDialog Then
            ret = mciSendString("Open " & Chr(34) & ofd.FileName & Chr(34) & " alias audio", CStr(0), 0, 0)
            ret = mciSendString("Open audio", CStr(0), 0, 0)
        End If
    End Sub


Get this bounty!!!